Now using SensorsUI
This commit is contained in:
@@ -17,27 +17,6 @@
|
||||
052FBCD5251F842C00C4322E /* CPUTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD1251F842C00C4322E /* CPUTemplate.pdf */; };
|
||||
052FBCD6251F842C00C4322E /* TemperatureTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD2251F842C00C4322E /* TemperatureTemplate.pdf */; };
|
||||
052FBCD7251F842C00C4322E /* SchedulerTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD3251F842C00C4322E /* SchedulerTemplate.pdf */; };
|
||||
05566A082990F85200E7A5F1 /* SensorIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669EA2990F85200E7A5F1 /* SensorIcon.swift */; };
|
||||
05566A092990F85200E7A5F1 /* SensorsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */; };
|
||||
05566A0A2990F85200E7A5F1 /* VoltageTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */; };
|
||||
05566A0B2990F85200E7A5F1 /* CurrentTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */; };
|
||||
05566A0C2990F85200E7A5F1 /* ThermalTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */; };
|
||||
05566A0D2990F85200E7A5F1 /* SensorValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F02990F85200E7A5F1 /* SensorValue.swift */; };
|
||||
05566A0E2990F85200E7A5F1 /* SensorHistoryData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F12990F85200E7A5F1 /* SensorHistoryData.swift */; };
|
||||
05566A0F2990F85200E7A5F1 /* ArrayIsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */; };
|
||||
05566A102990F85200E7A5F1 /* SensorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F32990F85200E7A5F1 /* SensorItem.swift */; };
|
||||
05566A112990F85200E7A5F1 /* SensorItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 055669F42990F85200E7A5F1 /* SensorItem.xib */; };
|
||||
05566A122990F85200E7A5F1 /* SensorsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 055669F62990F85200E7A5F1 /* SensorsWindowController.xib */; };
|
||||
05566A132990F85200E7A5F1 /* ArrayIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */; };
|
||||
05566A142990F85200E7A5F1 /* SensorGraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F92990F85200E7A5F1 /* SensorGraphView.swift */; };
|
||||
05566A152990F85200E7A5F1 /* NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FA2990F85200E7A5F1 /* NSImage.swift */; };
|
||||
05566A162990F85200E7A5F1 /* Sensors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FB2990F85200E7A5F1 /* Sensors.swift */; };
|
||||
05566A172990F85200E7A5F1 /* Synchronizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FC2990F85200E7A5F1 /* Synchronizable.swift */; };
|
||||
05566A182990F85200E7A5F1 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FD2990F85200E7A5F1 /* Colors.swift */; };
|
||||
05566A192990F85200E7A5F1 /* IOHIDData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05566A012990F85200E7A5F1 /* IOHIDData.swift */; };
|
||||
05566A1A2990F85200E7A5F1 /* IOHID.m in Sources */ = {isa = PBXBuildFile; fileRef = 05566A022990F85200E7A5F1 /* IOHID.m */; };
|
||||
05566A1B2990F85200E7A5F1 /* SMC.m in Sources */ = {isa = PBXBuildFile; fileRef = 05566A042990F85200E7A5F1 /* SMC.m */; };
|
||||
05566A1C2990F85200E7A5F1 /* SMCData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05566A052990F85200E7A5F1 /* SMCData.swift */; };
|
||||
05566A75299195F400E7A5F1 /* GraphWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05566A74299195F400E7A5F1 /* GraphWindowController.swift */; };
|
||||
05566A782991963400E7A5F1 /* GraphWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05566A772991963400E7A5F1 /* GraphWindowController.xib */; };
|
||||
055A9320252778C10070F771 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A931F252778C10070F771 /* InfoViewController.swift */; };
|
||||
@@ -53,6 +32,12 @@
|
||||
057F8B1B251D2A970048F1E1 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 057F8B1A251D2A970048F1E1 /* Icon.icns */; };
|
||||
057F8B65251D2D5F0048F1E1 /* GitHubUpdates.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 057F8B5C251D2D510048F1E1 /* GitHubUpdates.framework */; };
|
||||
057F8B67251D2D680048F1E1 /* GitHubUpdates.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 057F8B5C251D2D510048F1E1 /* GitHubUpdates.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
058B8EFC2994421200263FE9 /* IOHIDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058B8EFA2994421200263FE9 /* IOHIDKit.framework */; };
|
||||
058B8EFD2994421200263FE9 /* IOHIDKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 058B8EFA2994421200263FE9 /* IOHIDKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
058B8EFE2994421200263FE9 /* SensorsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058B8EF9299441F600263FE9 /* SensorsUI.framework */; };
|
||||
058B8EFF2994421200263FE9 /* SensorsUI.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 058B8EF9299441F600263FE9 /* SensorsUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
058B8F002994421200263FE9 /* SMCKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058B8EFB2994421200263FE9 /* SMCKit.framework */; };
|
||||
058B8F012994421200263FE9 /* SMCKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 058B8EFB2994421200263FE9 /* SMCKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
05AA407A251CF3D200106CEA /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */; };
|
||||
05AA407F251CF3D600106CEA /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05AA407D251CF3D600106CEA /* MainMenu.xib */; };
|
||||
05AA408D251CFA0600106CEA /* ThermalLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AA408C251CFA0600106CEA /* ThermalLog.swift */; };
|
||||
@@ -90,6 +75,13 @@
|
||||
remoteGlobalIDString = 05F82B241EF32EA700EC8A93;
|
||||
remoteInfo = GitHubUpdates;
|
||||
};
|
||||
058B8EF8299441F600263FE9 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 058B8EF1299441F500263FE9 /* SensorsUI.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 058B8EA22994383300263FE9;
|
||||
remoteInfo = SensorsUI;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -100,6 +92,9 @@
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
057F8B67251D2D680048F1E1 /* GitHubUpdates.framework in CopyFiles */,
|
||||
058B8EFF2994421200263FE9 /* SensorsUI.framework in CopyFiles */,
|
||||
058B8EFD2994421200263FE9 /* IOHIDKit.framework in CopyFiles */,
|
||||
058B8F012994421200263FE9 /* SMCKit.framework in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -116,31 +111,6 @@
|
||||
052FBCD1251F842C00C4322E /* CPUTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CPUTemplate.pdf; sourceTree = "<group>"; };
|
||||
052FBCD2251F842C00C4322E /* TemperatureTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = TemperatureTemplate.pdf; sourceTree = "<group>"; };
|
||||
052FBCD3251F842C00C4322E /* SchedulerTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = SchedulerTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EA2990F85200E7A5F1 /* SensorIcon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorIcon.swift; sourceTree = "<group>"; };
|
||||
055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorsWindowController.swift; sourceTree = "<group>"; };
|
||||
055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = VoltageTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CurrentTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ThermalTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669F02990F85200E7A5F1 /* SensorValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorValue.swift; sourceTree = "<group>"; };
|
||||
055669F12990F85200E7A5F1 /* SensorHistoryData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorHistoryData.swift; sourceTree = "<group>"; };
|
||||
055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsNotEmpty.swift; sourceTree = "<group>"; };
|
||||
055669F32990F85200E7A5F1 /* SensorItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorItem.swift; sourceTree = "<group>"; };
|
||||
055669F52990F85200E7A5F1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorItem.xib; sourceTree = "<group>"; };
|
||||
055669F72990F85200E7A5F1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorsWindowController.xib; sourceTree = "<group>"; };
|
||||
055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsEmpty.swift; sourceTree = "<group>"; };
|
||||
055669F92990F85200E7A5F1 /* SensorGraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorGraphView.swift; sourceTree = "<group>"; };
|
||||
055669FA2990F85200E7A5F1 /* NSImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSImage.swift; sourceTree = "<group>"; };
|
||||
055669FB2990F85200E7A5F1 /* Sensors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sensors.swift; sourceTree = "<group>"; };
|
||||
055669FC2990F85200E7A5F1 /* Synchronizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Synchronizable.swift; sourceTree = "<group>"; };
|
||||
055669FD2990F85200E7A5F1 /* Colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
|
||||
055669FF2990F85200E7A5F1 /* IOHID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOHID.h; sourceTree = "<group>"; };
|
||||
05566A002990F85200E7A5F1 /* IOHID-Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IOHID-Internal.h"; sourceTree = "<group>"; };
|
||||
05566A012990F85200E7A5F1 /* IOHIDData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOHIDData.swift; sourceTree = "<group>"; };
|
||||
05566A022990F85200E7A5F1 /* IOHID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IOHID.m; sourceTree = "<group>"; };
|
||||
05566A042990F85200E7A5F1 /* SMC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMC.m; sourceTree = "<group>"; };
|
||||
05566A052990F85200E7A5F1 /* SMCData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMCData.swift; sourceTree = "<group>"; };
|
||||
05566A062990F85200E7A5F1 /* SMC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMC.h; sourceTree = "<group>"; };
|
||||
05566A072990F85200E7A5F1 /* SMC-Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SMC-Internal.h"; sourceTree = "<group>"; };
|
||||
05566A74299195F400E7A5F1 /* GraphWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphWindowController.swift; sourceTree = "<group>"; };
|
||||
05566A772991963400E7A5F1 /* GraphWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GraphWindowController.xib; sourceTree = "<group>"; };
|
||||
055A931F252778C10070F771 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -203,6 +173,10 @@
|
||||
057F8B53251D2C840048F1E1 /* ccache.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ccache.sh; sourceTree = "<group>"; };
|
||||
057F8B54251D2C840048F1E1 /* Debug - zld.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Debug - zld.xcconfig"; sourceTree = "<group>"; };
|
||||
057F8B56251D2D510048F1E1 /* GitHubUpdates.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GitHubUpdates.xcodeproj; path = Submodules/GitHubUpdates/GitHubUpdates.xcodeproj; sourceTree = "<group>"; };
|
||||
058B8EEF299441CE00263FE9 /* CODE_OF_CONDUCT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CODE_OF_CONDUCT.md; sourceTree = "<group>"; };
|
||||
058B8EF1299441F500263FE9 /* SensorsUI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SensorsUI.xcodeproj; path = Submodules/Sensors/SensorsUI.xcodeproj; sourceTree = "<group>"; };
|
||||
058B8EFA2994421200263FE9 /* IOHIDKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = IOHIDKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
058B8EFB2994421200263FE9 /* SMCKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SMCKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05AA4076251CF3D200106CEA /* Hot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Hot.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; };
|
||||
05AA407E251CF3D600106CEA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@@ -226,68 +200,17 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
058B8EFC2994421200263FE9 /* IOHIDKit.framework in Frameworks */,
|
||||
052FBC34251ECA8600C4322E /* IOKit.framework in Frameworks */,
|
||||
058B8EFE2994421200263FE9 /* SensorsUI.framework in Frameworks */,
|
||||
057F8B65251D2D5F0048F1E1 /* GitHubUpdates.framework in Frameworks */,
|
||||
058B8F002994421200263FE9 /* SMCKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
055669E92990F85200E7A5F1 /* SensorsWindow */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669EA2990F85200E7A5F1 /* SensorIcon.swift */,
|
||||
055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */,
|
||||
055669EC2990F85200E7A5F1 /* Images */,
|
||||
055669F02990F85200E7A5F1 /* SensorValue.swift */,
|
||||
055669F12990F85200E7A5F1 /* SensorHistoryData.swift */,
|
||||
055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */,
|
||||
055669F32990F85200E7A5F1 /* SensorItem.swift */,
|
||||
055669F42990F85200E7A5F1 /* SensorItem.xib */,
|
||||
055669F62990F85200E7A5F1 /* SensorsWindowController.xib */,
|
||||
055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */,
|
||||
055669F92990F85200E7A5F1 /* SensorGraphView.swift */,
|
||||
055669FA2990F85200E7A5F1 /* NSImage.swift */,
|
||||
055669FB2990F85200E7A5F1 /* Sensors.swift */,
|
||||
055669FC2990F85200E7A5F1 /* Synchronizable.swift */,
|
||||
055669FD2990F85200E7A5F1 /* Colors.swift */,
|
||||
);
|
||||
path = SensorsWindow;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669EC2990F85200E7A5F1 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */,
|
||||
055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */,
|
||||
055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669FE2990F85200E7A5F1 /* IOHID */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669FF2990F85200E7A5F1 /* IOHID.h */,
|
||||
05566A002990F85200E7A5F1 /* IOHID-Internal.h */,
|
||||
05566A012990F85200E7A5F1 /* IOHIDData.swift */,
|
||||
05566A022990F85200E7A5F1 /* IOHID.m */,
|
||||
);
|
||||
path = IOHID;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05566A032990F85200E7A5F1 /* SMC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05566A042990F85200E7A5F1 /* SMC.m */,
|
||||
05566A052990F85200E7A5F1 /* SMCData.swift */,
|
||||
05566A062990F85200E7A5F1 /* SMC.h */,
|
||||
05566A072990F85200E7A5F1 /* SMC-Internal.h */,
|
||||
);
|
||||
path = SMC;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
057F8AFE251D22360048F1E1 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -436,16 +359,28 @@
|
||||
057F8B64251D2D5F0048F1E1 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
058B8EFA2994421200263FE9 /* IOHIDKit.framework */,
|
||||
058B8EFB2994421200263FE9 /* SMCKit.framework */,
|
||||
052FBC33251ECA8600C4322E /* IOKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
058B8EF2299441F500263FE9 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
058B8EF9299441F600263FE9 /* SensorsUI.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05AA406D251CF3D200106CEA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
057F8B1E251D2B900048F1E1 /* LICENSE */,
|
||||
057F8B1F251D2B900048F1E1 /* README.md */,
|
||||
058B8EEF299441CE00263FE9 /* CODE_OF_CONDUCT.md */,
|
||||
058B8EF1299441F500263FE9 /* SensorsUI.xcodeproj */,
|
||||
057F8B56251D2D510048F1E1 /* GitHubUpdates.xcodeproj */,
|
||||
057F8B20251D2C840048F1E1 /* xcconfig */,
|
||||
05AA4078251CF3D200106CEA /* Hot */,
|
||||
@@ -476,9 +411,6 @@
|
||||
05AA4088251CF3F400106CEA /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669FE2990F85200E7A5F1 /* IOHID */,
|
||||
055669E92990F85200E7A5F1 /* SensorsWindow */,
|
||||
05566A032990F85200E7A5F1 /* SMC */,
|
||||
057F8B0B251D273E0048F1E1 /* AboutWindowController.swift */,
|
||||
05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */,
|
||||
05221E87267009A8007246FF /* SensorViewController.swift */,
|
||||
@@ -569,6 +501,10 @@
|
||||
ProductGroup = 057F8B57251D2D510048F1E1 /* Products */;
|
||||
ProjectRef = 057F8B56251D2D510048F1E1 /* GitHubUpdates.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 058B8EF2299441F500263FE9 /* Products */;
|
||||
ProjectRef = 058B8EF1299441F500263FE9 /* SensorsUI.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
@@ -592,6 +528,13 @@
|
||||
remoteRef = 057F8B5D251D2D510048F1E1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
058B8EF9299441F600263FE9 /* SensorsUI.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
path = SensorsUI.framework;
|
||||
remoteRef = 058B8EF8299441F600263FE9 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
@@ -605,14 +548,11 @@
|
||||
057F8B00251D22360048F1E1 /* StatusIconTemplate.pdf in Resources */,
|
||||
057F8B1B251D2A970048F1E1 /* Icon.icns in Resources */,
|
||||
052FBCD5251F842C00C4322E /* CPUTemplate.pdf in Resources */,
|
||||
05566A0C2990F85200E7A5F1 /* ThermalTemplate.pdf in Resources */,
|
||||
05221E8B26700A57007246FF /* SensorViewController.xib in Resources */,
|
||||
05AD459229092CEB00A791C8 /* TCalTemplate.pdf in Resources */,
|
||||
05AD458C2908505900A791C8 /* SelectSensorsWindowController.xib in Resources */,
|
||||
055A9323252778D00070F771 /* InfoViewController.xib in Resources */,
|
||||
05B0DFA526714A830068FF9B /* UnknownTemplate.pdf in Resources */,
|
||||
05566A112990F85200E7A5F1 /* SensorItem.xib in Resources */,
|
||||
05566A0B2990F85200E7A5F1 /* CurrentTemplate.pdf in Resources */,
|
||||
05AD459029092B8400A791C8 /* BatteryTemplate.pdf in Resources */,
|
||||
057F8B15251D27650048F1E1 /* AboutWindowController.xib in Resources */,
|
||||
052FBCA7251EE46700C4322E /* PreferencesWindowController.xib in Resources */,
|
||||
@@ -620,8 +560,6 @@
|
||||
052FBCD7251F842C00C4322E /* SchedulerTemplate.pdf in Resources */,
|
||||
05B0DFA626714A830068FF9B /* eAccTemplate.pdf in Resources */,
|
||||
05566A782991963400E7A5F1 /* GraphWindowController.xib in Resources */,
|
||||
05566A0A2990F85200E7A5F1 /* VoltageTemplate.pdf in Resources */,
|
||||
05566A122990F85200E7A5F1 /* SensorsWindowController.xib in Resources */,
|
||||
05B0DFAA267150F40068FF9B /* TCXCTemplate.pdf in Resources */,
|
||||
05B0DFA426714A830068FF9B /* pAccTemplate.pdf in Resources */,
|
||||
);
|
||||
@@ -655,14 +593,8 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05566A0E2990F85200E7A5F1 /* SensorHistoryData.swift in Sources */,
|
||||
055A932525277E9E0070F771 /* IntegerToString.swift in Sources */,
|
||||
05566A172990F85200E7A5F1 /* Synchronizable.swift in Sources */,
|
||||
055A932725277F6E0070F771 /* TemperatureToString.swift in Sources */,
|
||||
05566A0D2990F85200E7A5F1 /* SensorValue.swift in Sources */,
|
||||
05566A1C2990F85200E7A5F1 /* SMCData.swift in Sources */,
|
||||
05566A192990F85200E7A5F1 /* IOHIDData.swift in Sources */,
|
||||
05566A152990F85200E7A5F1 /* NSImage.swift in Sources */,
|
||||
05221E8626700772007246FF /* DictionaryIsEmpty.swift in Sources */,
|
||||
052FBCA3251EE43B00C4322E /* PreferencesWindowController.swift in Sources */,
|
||||
055A932B252780FD0070F771 /* GraphView.swift in Sources */,
|
||||
@@ -670,22 +602,12 @@
|
||||
057F8B11251D274C0048F1E1 /* NSApplication+LaunchServices.m in Sources */,
|
||||
057F8B0C251D273E0048F1E1 /* AboutWindowController.swift in Sources */,
|
||||
055A9320252778C10070F771 /* InfoViewController.swift in Sources */,
|
||||
05566A162990F85200E7A5F1 /* Sensors.swift in Sources */,
|
||||
05566A102990F85200E7A5F1 /* SensorItem.swift in Sources */,
|
||||
05566A082990F85200E7A5F1 /* SensorIcon.swift in Sources */,
|
||||
05566A182990F85200E7A5F1 /* Colors.swift in Sources */,
|
||||
05566A092990F85200E7A5F1 /* SensorsWindowController.swift in Sources */,
|
||||
05AD458829084FEF00A791C8 /* SelectSensorsWindowController.swift in Sources */,
|
||||
05566A1A2990F85200E7A5F1 /* IOHID.m in Sources */,
|
||||
05566A0F2990F85200E7A5F1 /* ArrayIsNotEmpty.swift in Sources */,
|
||||
05566A75299195F400E7A5F1 /* GraphWindowController.swift in Sources */,
|
||||
05AA408D251CFA0600106CEA /* ThermalLog.swift in Sources */,
|
||||
055A932925277F990070F771 /* PercentToString.swift in Sources */,
|
||||
05566A132990F85200E7A5F1 /* ArrayIsEmpty.swift in Sources */,
|
||||
05AA407A251CF3D200106CEA /* ApplicationDelegate.swift in Sources */,
|
||||
05BA0BAA26F342DA00AA7BFC /* PressureToString.swift in Sources */,
|
||||
05566A1B2990F85200E7A5F1 /* SMC.m in Sources */,
|
||||
05566A142990F85200E7A5F1 /* SensorGraphView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -716,22 +638,6 @@
|
||||
name = PreferencesWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669F42990F85200E7A5F1 /* SensorItem.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
055669F52990F85200E7A5F1 /* Base */,
|
||||
);
|
||||
name = SensorItem.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669F62990F85200E7A5F1 /* SensorsWindowController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
055669F72990F85200E7A5F1 /* Base */,
|
||||
);
|
||||
name = SensorsWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055A9321252778D00070F771 /* InfoViewController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
* Copyright (c) 2023, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
import Cocoa
|
||||
import GitHubUpdates
|
||||
import SensorsUI
|
||||
|
||||
@NSApplicationMain
|
||||
class ApplicationDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate
|
||||
|
||||
@@ -23,5 +23,3 @@
|
||||
******************************************************************************/
|
||||
|
||||
#import "NSApplication+LaunchServices.h"
|
||||
#import "SMC.h"
|
||||
#import "IOHID.h"
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
@import IOKit;
|
||||
@import CoreFoundation;
|
||||
|
||||
#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
#import <IOKit/hidsystem/IOHIDServiceClient.h>
|
||||
#import <IOKit/hid/IOHIDKeys.h>
|
||||
|
||||
/* @see https://opensource.apple.com/source/IOHIDFamily/ */
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDPage )
|
||||
{
|
||||
IOHIDPageAppleVendor = 0xFF00,
|
||||
IOHIDPageAppleVendorKeyboard = 0xFF01,
|
||||
IOHIDPageAppleVendorMouse = 0xFF02,
|
||||
IOHIDPageAppleVendorAccelerometer = 0xFF03,
|
||||
IOHIDPageAppleVendorAmbientLightSensor = 0xFF04,
|
||||
IOHIDPageAppleVendorTemperatureSensor = 0xFF05,
|
||||
IOHIDPageAppleVendorHeadset = 0xFF07,
|
||||
IOHIDPageAppleVendorPowerSensor = 0xFF08,
|
||||
IOHIDPageAppleVendorSmartCover = 0xFF09,
|
||||
IOHIDPageAppleVendorPlatinum = 0xFF0A,
|
||||
IOHIDPageAppleVendorLisa = 0xFF0B,
|
||||
IOHIDPageAppleVendorMotion = 0xFF0C,
|
||||
IOHIDPageAppleVendorBattery = 0xFF0D,
|
||||
IOHIDPageAppleVendorIRRemote = 0xFF0E,
|
||||
IOHIDPageAppleVendorDebug = 0xFF0F,
|
||||
IOHIDPageAppleVendorFilteredEvent = 0xFF50,
|
||||
IOHIDPageAppleVendorMultitouch = 0xFF60,
|
||||
IOHIDPageAppleVendorDisplay = 0xFF92,
|
||||
IOHIDPageAppleVendorTopCase = 0x00FF
|
||||
};
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDUsageAppleVendor )
|
||||
{
|
||||
IOHIDUsageAppleVendorTopCase = 0x01,
|
||||
IOHIDUsageAppleVendorDisplay = 0x02,
|
||||
IOHIDUsageAppleVendorAccelerometer = 0x03,
|
||||
IOHIDUsageAppleVendorAmbientLightSensor = 0x04,
|
||||
IOHIDUsageAppleVendorTemperatureSensor = 0x05,
|
||||
IOHIDUsageAppleVendorKeyboard = 0x06,
|
||||
IOHIDUsageAppleVendorHeadset = 0x07,
|
||||
IOHIDUsageAppleVendorProximitySensor = 0x08,
|
||||
IOHIDUsageAppleVendorGyro = 0x09,
|
||||
IOHIDUsageAppleVendorCompass = 0x0A,
|
||||
IOHIDUsageAppleVendorDeviceManagement = 0x0B,
|
||||
IOHIDUsageAppleVendorTrackpad = 0x0C,
|
||||
IOHIDUsageAppleVendorTopCaseReserved = 0x0D,
|
||||
IOHIDUsageAppleVendorMotion = 0x0E,
|
||||
IOHIDUsageAppleVendorKeyboardBacklight = 0x0F,
|
||||
IOHIDUsageAppleVendorDeviceMotionLite = 0x10,
|
||||
IOHIDUsageAppleVendorForce = 0x11,
|
||||
IOHIDUsageAppleVendorBluetoothRadio = 0x12,
|
||||
IOHIDUsageAppleVendorOrb = 0x13,
|
||||
IOHIDUsageAppleVendorAccessoryBattery = 0x14
|
||||
};
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDUsageAppleVendorPowerSensor )
|
||||
{
|
||||
IOHIDUsageAppleVendorPowerSensorPower = 0x1,
|
||||
IOHIDUsageAppleVendorPowerSensorCurrent = 0x2,
|
||||
IOHIDUsageAppleVendorPowerSensorVoltage = 0x3
|
||||
};
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDEvent )
|
||||
{
|
||||
IOHIDEventTypeNULL = 0x00,
|
||||
IOHIDEventTypeVendorDefined = 0x01,
|
||||
IOHIDEventTypeButton = 0x02,
|
||||
IOHIDEventTypeKeyboard = 0x03,
|
||||
IOHIDEventTypeTranslation = 0x04,
|
||||
IOHIDEventTypeRotation = 0x05,
|
||||
IOHIDEventTypeScroll = 0x06,
|
||||
IOHIDEventTypeScale = 0x07,
|
||||
IOHIDEventTypeZoom = 0x08,
|
||||
IOHIDEventTypeVelocity = 0x09,
|
||||
IOHIDEventTypeOrientation = 0x0A,
|
||||
IOHIDEventTypeDigitizer = 0x0B,
|
||||
IOHIDEventTypeAmbientLightSensor = 0x0C,
|
||||
IOHIDEventTypeAccelerometer = 0x0D,
|
||||
IOHIDEventTypeProximity = 0x0E,
|
||||
IOHIDEventTypeTemperature = 0x0F,
|
||||
IOHIDEventTypeNavigationSwipe = 0x10,
|
||||
IOHIDEventTypeSwipe = IOHIDEventTypeNavigationSwipe,
|
||||
IOHIDEventTypeMouse = 0x11,
|
||||
IOHIDEventTypeProgress = 0x12,
|
||||
IOHIDEventTypeCount = 0x13,
|
||||
IOHIDEventTypeGyro = 0x14,
|
||||
IOHIDEventTypeCompass = 0x15,
|
||||
IOHIDEventTypeZoomToggle = 0x16,
|
||||
IOHIDEventTypeDockSwipe = 0x17,
|
||||
IOHIDEventTypeSymbolicHotKey = 0x18,
|
||||
IOHIDEventTypePower = 0x19,
|
||||
IOHIDEventTypeBrightness = 0x1A,
|
||||
IOHIDEventTypeFluidTouchGesture = 0x1B,
|
||||
IOHIDEventTypeBoundaryScroll = 0x1C,
|
||||
IOHIDEventTypeReset = 0x1D
|
||||
};
|
||||
|
||||
#define IOHIDEventFieldBase( _type_ ) ( _type_ << 16 )
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDEventField )
|
||||
{
|
||||
IOHIDEventFieldTemperatureLevel = IOHIDEventFieldBase( IOHIDEventTypeTemperature ),
|
||||
IOHIDEventFieldPowerMeasurement = IOHIDEventFieldBase( IOHIDEventTypePower )
|
||||
};
|
||||
|
||||
extern IOHIDEventSystemClientRef IOHIDEventSystemClientCreate( CFAllocatorRef );
|
||||
extern void IOHIDEventSystemClientSetMatching( IOHIDEventSystemClientRef, CFDictionaryRef );
|
||||
extern CFTypeRef IOHIDServiceClientCopyEvent( IOHIDServiceClientRef, IOHIDEvent, int64_t, int64_t );
|
||||
extern CFDictionaryRef IOHIDServiceClientCopyProperties( IOHIDServiceClientRef, CFArrayRef );
|
||||
extern double IOHIDEventGetFloatValue( CFTypeRef, int64_t );
|
||||
@@ -1,42 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class IOHIDData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface IOHID: NSObject
|
||||
|
||||
@property( class, nonatomic, readonly ) IOHID * shared;
|
||||
|
||||
- ( instancetype )init;
|
||||
- ( NSArray< IOHIDData * > * )readTemperatureSensors;
|
||||
- ( NSArray< IOHIDData * > * )readVoltageSensors;
|
||||
- ( NSArray< IOHIDData * > * )readCurrentSensors;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,130 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "IOHID.h"
|
||||
#import "IOHID-Internal.h"
|
||||
#import "Hot-Swift.h"
|
||||
#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
#import <IOKit/hidsystem/IOHIDServiceClient.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface IOHID()
|
||||
|
||||
@property( nonatomic, readwrite, assign, nullable ) IOHIDEventSystemClientRef client;
|
||||
|
||||
- ( NSArray< IOHIDData * > * )read: ( long long )page usage: ( int64_t )usage eventType: ( int64_t )eventType eventField: ( int64_t )eventField;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation IOHID
|
||||
|
||||
+ ( IOHID * )shared
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
static IOHID * instance;
|
||||
|
||||
dispatch_once
|
||||
(
|
||||
&once,
|
||||
^( void )
|
||||
{
|
||||
instance = [ IOHID new ];
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
- ( instancetype )init
|
||||
{
|
||||
if( ( self = [ super init ] ) )
|
||||
{
|
||||
self.client = IOHIDEventSystemClientCreate( kCFAllocatorDefault );
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- ( oneway void )dealloc
|
||||
{
|
||||
CFRelease( self.client );
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readTemperatureSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendor usage: IOHIDUsageAppleVendorTemperatureSensor eventType: IOHIDEventTypeTemperature eventField: IOHIDEventFieldTemperatureLevel ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readVoltageSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorVoltage eventType: IOHIDEventTypePower eventField: IOHIDEventFieldPowerMeasurement ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readCurrentSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorCurrent eventType: IOHIDEventTypePower eventField: IOHIDEventFieldPowerMeasurement ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )read: ( long long )page usage: ( int64_t )usage eventType: ( int64_t )eventType eventField: ( int64_t )eventField
|
||||
{
|
||||
if( self.client == nil )
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
NSDictionary * filter =
|
||||
@{
|
||||
@"PrimaryUsagePage" : [ NSNumber numberWithLongLong: page ],
|
||||
@"PrimaryUsage" : [ NSNumber numberWithLongLong: usage ]
|
||||
};
|
||||
|
||||
IOHIDEventSystemClientSetMatching( self.client, ( __bridge CFDictionaryRef )filter );
|
||||
|
||||
NSArray * services = CFBridgingRelease( IOHIDEventSystemClientCopyServices( ( IOHIDEventSystemClientRef )( self.client ) ) );
|
||||
NSMutableDictionary< NSString *, IOHIDData * > * values = [ NSMutableDictionary new ];
|
||||
|
||||
for( id o in services )
|
||||
{
|
||||
IOHIDServiceClientRef service = ( __bridge IOHIDServiceClientRef )o;
|
||||
NSString * name = CFBridgingRelease( IOHIDServiceClientCopyProperty( service, CFSTR( "Product" ) ) );
|
||||
CFTypeRef event = IOHIDServiceClientCopyEvent( service, eventType, 0, 0 );
|
||||
|
||||
if( name != nil && event != nil )
|
||||
{
|
||||
values[ name ] = [ [ IOHIDData alloc ] initWithName: name value: IOHIDEventGetFloatValue( event, eventField ) ];
|
||||
}
|
||||
|
||||
if( event != nil )
|
||||
{
|
||||
CFRelease( event );
|
||||
}
|
||||
}
|
||||
|
||||
return [ values allValues ];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,39 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class IOHIDData: NSObject
|
||||
{
|
||||
@objc public dynamic var name: String
|
||||
@objc public dynamic var value: Double
|
||||
|
||||
@objc
|
||||
public init( name: String, value: Double )
|
||||
{
|
||||
self.name = name
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
@import IOKit;
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
* - https://github.com/apple-oss-distributions/IOKitUser
|
||||
* - https://opensource.apple.com/source/IOKitUser/
|
||||
* - https://opensource.apple.com/source/IOKitUser/IOKitUser-647.6/pwr_mgt.subproj/IOPMLibPrivate.c
|
||||
*/
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCKeyNotFound = 0x84
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCSuccess = 0,
|
||||
kSMCError = 1
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCUserClientOpen = 0,
|
||||
kSMCUserClientClose = 1,
|
||||
kSMCHandleYPCEvent = 2,
|
||||
kSMCReadKey = 5,
|
||||
kSMCWriteKey = 6,
|
||||
kSMCGetKeyCount = 7,
|
||||
kSMCGetKeyFromIndex = 8,
|
||||
kSMCGetKeyInfo = 9
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned char build;
|
||||
unsigned char reserved;
|
||||
unsigned short release;
|
||||
}
|
||||
SMCVersion;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t version;
|
||||
uint16_t length;
|
||||
uint32_t cpuPLimit;
|
||||
uint32_t gpuPLimit;
|
||||
uint32_t memPLimit;
|
||||
}
|
||||
SMCPLimitData;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dataSize;
|
||||
uint32_t dataType;
|
||||
uint8_t dataAttributes;
|
||||
}
|
||||
SMCKeyInfoData;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t key;
|
||||
SMCVersion vers;
|
||||
SMCPLimitData pLimitData;
|
||||
SMCKeyInfoData keyInfo;
|
||||
uint8_t result;
|
||||
uint8_t status;
|
||||
uint8_t data8;
|
||||
uint32_t data32;
|
||||
uint8_t bytes[ 32 ];
|
||||
}
|
||||
SMCParamStruct;
|
||||
|
||||
extern const uint32_t kSMCKeyNKEY;
|
||||
extern const uint32_t kSMCKeyACID;
|
||||
@@ -1,40 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class SMCData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface SMC: NSObject
|
||||
|
||||
@property( class, nonatomic, readonly ) SMC * shared;
|
||||
|
||||
- ( instancetype )init;
|
||||
- ( NSArray< SMCData * > * )readAllKeys: ( BOOL ( ^ _Nullable )( uint32_t ) )filter;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,410 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "SMC.h"
|
||||
#import "SMC-Internal.h"
|
||||
#import "Hot-Swift.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
|
||||
const uint32_t kSMCKeyNKEY = '#KEY';
|
||||
const uint32_t kSMCKeyACID = 'ACID';
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
@import IOKit;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface SMC()
|
||||
|
||||
@property( nonatomic, readwrite, assign ) io_connect_t connection;
|
||||
@property( nonatomic, readwrite, strong ) NSMutableArray< NSNumber * > * keys;
|
||||
@property( nonatomic, readwrite, strong ) NSMutableDictionary< NSNumber *, NSValue * > * keyInfoCache;
|
||||
|
||||
+ ( NSError * )errorWithTitle: ( NSString * )title message: ( NSString * )message code: ( NSInteger )code;
|
||||
- ( BOOL )callSMCFunction: ( uint32_t )function input: ( const SMCParamStruct * )input output: ( SMCParamStruct * )output;
|
||||
- ( BOOL )readSMCKeyInfo: ( SMCKeyInfoData * )info forKey: ( uint32_t )key;
|
||||
- ( BOOL )readSMCKey: ( uint32_t * )key atIndex: ( uint32_t )index;
|
||||
- ( BOOL )readSMCKey: ( uint32_t )key buffer: ( uint8_t * )buffer maxSize: ( uint32_t * )maxSize keyInfo: ( SMCKeyInfoData * _Nullable )keyInfo;
|
||||
- ( uint32_t )readSMCKeyCount;
|
||||
- ( uint32_t )readInteger: ( uint8_t * )data size: ( uint32_t )size;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation SMC
|
||||
|
||||
+ ( SMC * )shared
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
static SMC * instance;
|
||||
|
||||
dispatch_once
|
||||
(
|
||||
&once,
|
||||
^( void )
|
||||
{
|
||||
instance = [ SMC new ];
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ ( NSError * )errorWithTitle: ( NSString * )title message: ( NSString * )message code: ( NSInteger )code
|
||||
{
|
||||
NSDictionary * info =
|
||||
@{
|
||||
NSLocalizedDescriptionKey: title,
|
||||
NSLocalizedRecoverySuggestionErrorKey: message
|
||||
};
|
||||
|
||||
return [ [ NSError alloc ] initWithDomain: NSCocoaErrorDomain code: code userInfo: info ];
|
||||
}
|
||||
|
||||
- ( instancetype )init
|
||||
{
|
||||
if( ( self = [ super init ] ) )
|
||||
{
|
||||
self.keys = [ NSMutableArray new ];
|
||||
self.keyInfoCache = [ NSMutableDictionary new ];
|
||||
|
||||
[ self open: nil ];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- ( oneway void )dealloc
|
||||
{
|
||||
[ self close ];
|
||||
}
|
||||
|
||||
- ( NSArray< SMCData * > * )readAllKeys: ( BOOL ( ^ _Nullable )( uint32_t ) )filter
|
||||
{
|
||||
if( self.connection == IO_OBJECT_NULL )
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
if( self.keys.count == 0 )
|
||||
{
|
||||
uint32_t count = [ self readSMCKeyCount ];
|
||||
|
||||
for( uint32_t i = 0; i < count; i++ )
|
||||
{
|
||||
uint32_t key = 0;
|
||||
|
||||
if( [ self readSMCKey: &key atIndex: i ] == NO )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( key != 0 )
|
||||
{
|
||||
[ self.keys addObject: [ NSNumber numberWithUnsignedInt: key ] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableArray< SMCData * > * items = [ [ NSMutableArray alloc ] initWithCapacity: self.keys.count ];
|
||||
|
||||
for( NSNumber * key in self.keys )
|
||||
{
|
||||
if( filter != nil && filter( key.unsignedIntValue ) == NO )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SMCKeyInfoData info;
|
||||
uint8_t data[ 32 ];
|
||||
uint32_t size = sizeof( data );
|
||||
|
||||
if( [ self readSMCKey: key.unsignedIntValue buffer: data maxSize: &size keyInfo: &info ] == NO )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SMCData * item = [ [ SMCData alloc ] initWithKey: key.unsignedIntValue type: info.dataType data: [ NSData dataWithBytes: data length: size ] ];
|
||||
|
||||
[ items addObject: item ];
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
- ( BOOL )open: ( NSError * _Nullable __autoreleasing * )error
|
||||
{
|
||||
if( self.connection != IO_OBJECT_NULL )
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
io_service_t smc = IOServiceGetMatchingService( kIOMasterPortDefault, IOServiceMatching( "AppleSMC" ) );
|
||||
|
||||
if( smc == IO_OBJECT_NULL )
|
||||
{
|
||||
if( error )
|
||||
{
|
||||
*( error ) = [ SMC errorWithTitle: @"Cannot Open SMC" message: @"Unable to retrieve the SMC service." code: -1 ];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
io_connect_t connection = IO_OBJECT_NULL;
|
||||
kern_return_t result = IOServiceOpen( smc, mach_task_self(), 0, &connection );
|
||||
|
||||
if( result != kIOReturnSuccess || connection == IO_OBJECT_NULL )
|
||||
{
|
||||
if( error )
|
||||
{
|
||||
*( error ) = [ SMC errorWithTitle: @"Cannot Open SMC" message: @"Unable to open the SMC service." code: -1 ];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
self.connection = connection;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )close
|
||||
{
|
||||
if( self.connection == IO_OBJECT_NULL )
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
if( IOServiceClose( self.connection ) != kIOReturnSuccess )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self.connection = IO_OBJECT_NULL;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )callSMCFunction: ( uint32_t )function input: ( const SMCParamStruct * )input output: ( SMCParamStruct * )output
|
||||
{
|
||||
size_t inputSize = sizeof( SMCParamStruct );
|
||||
size_t outputSize = sizeof( SMCParamStruct );
|
||||
kern_return_t result = IOConnectCallMethod( self.connection, kSMCUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
|
||||
if( result != kIOReturnSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
result = IOConnectCallStructMethod( self.connection, function, input, inputSize, output, &outputSize );
|
||||
|
||||
IOConnectCallMethod( self.connection, kSMCUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
|
||||
return result == kIOReturnSuccess;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKeyInfo: ( SMCKeyInfoData * )info forKey: ( uint32_t )key
|
||||
{
|
||||
if( info == NULL || key == 0 )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
{
|
||||
NSValue * cached = self.keyInfoCache[ [ NSNumber numberWithUnsignedInt: key ] ];
|
||||
|
||||
if( cached != nil )
|
||||
{
|
||||
*( info ) = *( ( SMCKeyInfoData * )( cached.pointerValue ) );
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.data8 = kSMCGetKeyInfo;
|
||||
input.key = key;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
*( info ) = output.keyInfo;
|
||||
|
||||
{
|
||||
SMCKeyInfoData * cached = calloc( sizeof( SMCKeyInfoData ), 1 );
|
||||
|
||||
if( cached != NULL )
|
||||
{
|
||||
*( cached ) = output.keyInfo;
|
||||
self.keyInfoCache[ [ NSNumber numberWithUnsignedInt: key ] ] = [ NSValue valueWithPointer: cached ];
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKey: ( uint32_t * )key atIndex: ( uint32_t )index
|
||||
{
|
||||
if( key == NULL )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.data8 = kSMCGetKeyFromIndex;
|
||||
input.data32 = index;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
*( key ) = output.key;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKey: ( uint32_t )key buffer: ( uint8_t * )buffer maxSize: ( uint32_t * )maxSize keyInfo: ( SMCKeyInfoData * _Nullable )keyInfo
|
||||
{
|
||||
if( key == 0 || buffer == NULL || maxSize == NULL )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCKeyInfoData info;
|
||||
|
||||
if( [ self readSMCKeyInfo: &info forKey: key ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.key = key;
|
||||
input.data8 = kSMCReadKey;
|
||||
input.keyInfo.dataSize = info.dataSize;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( *( maxSize ) < info.dataSize )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( keyInfo != NULL )
|
||||
{
|
||||
*( keyInfo ) = info;
|
||||
}
|
||||
|
||||
*( maxSize ) = info.dataSize;
|
||||
|
||||
bzero( buffer, *( maxSize ) );
|
||||
|
||||
for( uint32_t i = 0; i < info.dataSize; i++ )
|
||||
{
|
||||
if( key == kSMCKeyACID )
|
||||
{
|
||||
buffer[ i ] = output.bytes[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[ i ] = output.bytes[ info.dataSize - ( i + 1 ) ];
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( uint32_t )readSMCKeyCount
|
||||
{
|
||||
uint8_t data[ 8 ];
|
||||
uint32_t size = sizeof( data );
|
||||
|
||||
bzero( data, size );
|
||||
|
||||
if( [ self readSMCKey: kSMCKeyNKEY buffer: data maxSize: &size keyInfo: NULL ] == NO )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return [ self readInteger: data size: size ];
|
||||
}
|
||||
|
||||
- ( uint32_t )readInteger: ( uint8_t * )data size: ( uint32_t )size
|
||||
{
|
||||
uint32_t n = 0;
|
||||
|
||||
if( size > sizeof( uint32_t ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( uint32_t i = 0; i < size; i++ )
|
||||
{
|
||||
n |= ( uint32_t )( data[ i ] ) << ( i * 8 );
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,180 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class SMCData: NSObject
|
||||
{
|
||||
@objc public dynamic var key: UInt32
|
||||
@objc public dynamic var type: UInt32
|
||||
@objc public dynamic var data: Data
|
||||
@objc public dynamic var value: Any?
|
||||
|
||||
@objc public var keyName: String
|
||||
{
|
||||
SMCData.fourCC( value: self.key )
|
||||
}
|
||||
|
||||
@objc public var typeName: String
|
||||
{
|
||||
SMCData.fourCC( value: self.type )
|
||||
}
|
||||
|
||||
@objc
|
||||
public init( key: UInt32, type: UInt32, data: Data )
|
||||
{
|
||||
self.key = key
|
||||
self.type = type
|
||||
self.data = data
|
||||
self.value = SMCData.value( for: data, type: type )
|
||||
}
|
||||
|
||||
private class func fourCC( value: UInt32 ) -> String
|
||||
{
|
||||
let c1 = UInt8( ( value >> 24 ) & 0xFF )
|
||||
let c2 = UInt8( ( value >> 16 ) & 0xFF )
|
||||
let c3 = UInt8( ( value >> 8 ) & 0xFF )
|
||||
let c4 = UInt8( ( value >> 0 ) & 0xFF )
|
||||
|
||||
return String( format: "%c%c%c%c", c1, c2, c3, c4 )
|
||||
}
|
||||
|
||||
private class func value( for data: Data, type: UInt32 ) -> Any?
|
||||
{
|
||||
switch self.fourCC( value: type )
|
||||
{
|
||||
case "si8 ": return self.sint8( data: data ).byteSwapped
|
||||
case "ui8 ": return self.uint8( data: data ).byteSwapped
|
||||
case "si16": return self.sint16( data: data ).byteSwapped
|
||||
case "ui16": return self.uint16( data: data ).byteSwapped
|
||||
case "si32": return self.sint32( data: data ).byteSwapped
|
||||
case "ui32": return self.uint32( data: data ).byteSwapped
|
||||
case "si64": return self.sint64( data: data ).byteSwapped
|
||||
case "ui64": return self.uint64( data: data ).byteSwapped
|
||||
case "flt ": return self.float32( data: data )
|
||||
case "ioft": return self.ioFloat( data: data )
|
||||
case "sp78": return self.sp78( data: data )
|
||||
case "flag": return data[ 0 ] == 1 ? "True" : "False"
|
||||
case "ch8*": return String( data: Data( data.reversed() ), encoding: .utf8 )
|
||||
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
private class func sint8( data: Data ) -> Int8
|
||||
{
|
||||
Int8( bitPattern: self.uint8( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint16( data: Data ) -> Int16
|
||||
{
|
||||
Int16( bitPattern: self.uint16( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint32( data: Data ) -> Int32
|
||||
{
|
||||
Int32( bitPattern: self.uint32( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint64( data: Data ) -> Int64
|
||||
{
|
||||
Int64( bitPattern: self.uint64( data: data ) )
|
||||
}
|
||||
|
||||
private class func uint8( data: Data ) -> UInt8
|
||||
{
|
||||
UInt8( data[ 0 ] )
|
||||
}
|
||||
|
||||
private class func uint16( data: Data ) -> UInt16
|
||||
{
|
||||
let u1 = UInt16( data[ 0 ] ) << 8
|
||||
let u2 = UInt16( data[ 1 ] ) << 0
|
||||
|
||||
return u1 | u2
|
||||
}
|
||||
|
||||
private class func uint32( data: Data ) -> UInt32
|
||||
{
|
||||
let u1 = UInt32( data[ 0 ] ) << 24
|
||||
let u2 = UInt32( data[ 1 ] ) << 16
|
||||
let u3 = UInt32( data[ 2 ] ) << 8
|
||||
let u4 = UInt32( data[ 3 ] ) << 0
|
||||
|
||||
return u1 | u2 | u3 | u4
|
||||
}
|
||||
|
||||
private class func uint64( data: Data ) -> UInt64
|
||||
{
|
||||
let u1 = UInt64( data[ 0 ] ) << 56
|
||||
let u2 = UInt64( data[ 1 ] ) << 48
|
||||
let u3 = UInt64( data[ 2 ] ) << 40
|
||||
let u4 = UInt64( data[ 3 ] ) << 32
|
||||
let u5 = UInt64( data[ 4 ] ) << 24
|
||||
let u6 = UInt64( data[ 5 ] ) << 16
|
||||
let u7 = UInt64( data[ 6 ] ) << 8
|
||||
let u8 = UInt64( data[ 7 ] ) << 0
|
||||
|
||||
return u1 | u2 | u3 | u4 | u5 | u6 | u7 | u8
|
||||
}
|
||||
|
||||
private class func float32( data: Data ) -> Float32
|
||||
{
|
||||
Float32( bitPattern: self.uint32( data: data ) )
|
||||
}
|
||||
|
||||
private class func float64( data: Data ) -> Float64
|
||||
{
|
||||
Float64( bitPattern: self.uint64( data: data ) )
|
||||
}
|
||||
|
||||
private class func ioFloat( data: Data ) -> Double
|
||||
{
|
||||
if data.count != 8
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
let u64 = self.uint64( data: data )
|
||||
let integral = Double( u64 >> 16 )
|
||||
let mask = pow( 2.0, 16.0 ) - 1
|
||||
let fractional = Double( u64 & UInt64( mask ) ) / Double( 1 << 16 )
|
||||
|
||||
return integral + fractional
|
||||
}
|
||||
|
||||
private class func sp78( data: Data ) -> Double
|
||||
{
|
||||
if data.count != 2
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
let b1 = Double( data[ 1 ] & 0x7F )
|
||||
let b2 = Double( data[ 0 ] ) / Double( 1 << 8 )
|
||||
|
||||
return b1 + b2
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc( ArrayIsEmpty )
|
||||
public class ArrayIsEmpty: ValueTransformer
|
||||
{
|
||||
public override class func transformedValueClass() -> AnyClass
|
||||
{
|
||||
NSNumber.self
|
||||
}
|
||||
|
||||
public override class func allowsReverseTransformation() -> Bool
|
||||
{
|
||||
false
|
||||
}
|
||||
|
||||
public override func transformedValue( _ value: Any? ) -> Any?
|
||||
{
|
||||
guard let array = value as? NSArray
|
||||
else
|
||||
{
|
||||
return NSNumber( booleanLiteral: true )
|
||||
}
|
||||
|
||||
return NSNumber( booleanLiteral: array.count == 0 )
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc( ArrayIsNotEmpty )
|
||||
public class ArrayIsNotEmpty: ValueTransformer
|
||||
{
|
||||
public override class func transformedValueClass() -> AnyClass
|
||||
{
|
||||
NSNumber.self
|
||||
}
|
||||
|
||||
public override class func allowsReverseTransformation() -> Bool
|
||||
{
|
||||
false
|
||||
}
|
||||
|
||||
public override func transformedValue( _ value: Any? ) -> Any?
|
||||
{
|
||||
guard let array = value as? NSArray
|
||||
else
|
||||
{
|
||||
return NSNumber( booleanLiteral: false )
|
||||
}
|
||||
|
||||
return NSNumber( booleanLiteral: array.count > 0 )
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner"/>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="c22-O7-iKe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="245" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Zhs-tE-zrk">
|
||||
<rect key="frame" x="0.0" y="100" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="g2z-r1-gYP"/>
|
||||
<constraint firstAttribute="width" constant="20" id="kP1-0x-y1M"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="NSApplicationIcon" id="YpG-g1-XTw"/>
|
||||
<connections>
|
||||
<binding destination="ek2-AR-oS5" name="value" keyPath="self.sensor" id="EbR-ou-eai">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">SensorIcon</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Vx7-2w-JY2">
|
||||
<rect key="frame" x="26" y="105" width="28" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="truncatingTail" title="Label" id="4QE-tU-2iF">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="ek2-AR-oS5" name="toolTip" keyPath="self.sensor.name" id="sk7-rh-Bgb"/>
|
||||
<binding destination="ek2-AR-oS5" name="value" keyPath="self.sensor.name" id="COB-ax-oMZ"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qyW-PJ-lOk">
|
||||
<rect key="frame" x="219" y="105" width="28" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="truncatingTail" title="Label" id="05S-DK-Pm8">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="ek2-AR-oS5" name="toolTip" keyPath="self.sensor.name" id="RUP-1u-HBl"/>
|
||||
<binding destination="ek2-AR-oS5" name="value" keyPath="self.sensor.last" id="671-ZR-hc1">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">SensorValue</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="XSC-DH-60t">
|
||||
<rect key="frame" x="0.0" y="19" width="245" height="73"/>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KB3-h4-RKJ">
|
||||
<rect key="frame" x="-2" y="0.0" width="23" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="clipping" title="Min:" id="P1F-RJ-VTt">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WDq-1D-eKf">
|
||||
<rect key="frame" x="25" y="0.0" width="28" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="clipping" title="Label" id="pVf-bC-aUU">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="ek2-AR-oS5" name="value" keyPath="self.sensor.min" id="Hz7-WE-4XS">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">SensorValue</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PeT-bn-qut">
|
||||
<rect key="frame" x="190" y="0.0" width="25" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="clipping" title="Max:" id="piP-vw-2QX">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zT4-AQ-MeS">
|
||||
<rect key="frame" x="219" y="0.0" width="28" height="11"/>
|
||||
<textFieldCell key="cell" controlSize="mini" lineBreakMode="clipping" title="Label" id="0uv-Pe-gZH">
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="ek2-AR-oS5" name="value" keyPath="self.sensor.max" id="q5h-49-6GI">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">SensorValue</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="qyW-PJ-lOk" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Vx7-2w-JY2" secondAttribute="trailing" constant="8" symbolic="YES" id="37w-zR-zSG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="zT4-AQ-MeS" secondAttribute="bottom" id="6Eb-Jb-ktv"/>
|
||||
<constraint firstItem="zT4-AQ-MeS" firstAttribute="leading" secondItem="PeT-bn-qut" secondAttribute="trailing" constant="8" symbolic="YES" id="6Iv-Zk-l6p"/>
|
||||
<constraint firstItem="Vx7-2w-JY2" firstAttribute="centerY" secondItem="Zhs-tE-zrk" secondAttribute="centerY" id="E6p-Sp-hhE"/>
|
||||
<constraint firstItem="Zhs-tE-zrk" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="F4w-Ta-FMp"/>
|
||||
<constraint firstItem="zT4-AQ-MeS" firstAttribute="centerY" secondItem="PeT-bn-qut" secondAttribute="centerY" id="GLP-jq-o9j"/>
|
||||
<constraint firstItem="Zhs-tE-zrk" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="H4R-eE-jNf"/>
|
||||
<constraint firstItem="KB3-h4-RKJ" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="LlD-cK-jrf"/>
|
||||
<constraint firstItem="XSC-DH-60t" firstAttribute="top" secondItem="Zhs-tE-zrk" secondAttribute="bottom" constant="8" symbolic="YES" id="RBs-v9-fzB"/>
|
||||
<constraint firstItem="XSC-DH-60t" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="Y8P-AG-Uex"/>
|
||||
<constraint firstItem="qyW-PJ-lOk" firstAttribute="centerY" secondItem="Vx7-2w-JY2" secondAttribute="centerY" id="ZfP-Ip-Qp3"/>
|
||||
<constraint firstItem="WDq-1D-eKf" firstAttribute="leading" secondItem="KB3-h4-RKJ" secondAttribute="trailing" constant="8" symbolic="YES" id="bnr-IM-2mn"/>
|
||||
<constraint firstItem="PeT-bn-qut" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="WDq-1D-eKf" secondAttribute="trailing" constant="8" symbolic="YES" id="dRS-W2-HF3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="KB3-h4-RKJ" secondAttribute="bottom" id="gjk-x9-oBq"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zT4-AQ-MeS" secondAttribute="trailing" id="ivM-u5-F81"/>
|
||||
<constraint firstItem="WDq-1D-eKf" firstAttribute="centerY" secondItem="KB3-h4-RKJ" secondAttribute="centerY" id="k8I-Sa-B0p"/>
|
||||
<constraint firstAttribute="trailing" secondItem="XSC-DH-60t" secondAttribute="trailing" id="ma2-2p-gXZ"/>
|
||||
<constraint firstItem="Vx7-2w-JY2" firstAttribute="leading" secondItem="Zhs-tE-zrk" secondAttribute="trailing" constant="8" symbolic="YES" id="pSn-l6-1WW"/>
|
||||
<constraint firstItem="KB3-h4-RKJ" firstAttribute="top" secondItem="XSC-DH-60t" secondAttribute="bottom" constant="8" symbolic="YES" id="v2T-jr-FYT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qyW-PJ-lOk" secondAttribute="trailing" id="zrr-cs-S3r"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="26.5" y="125"/>
|
||||
</customView>
|
||||
<collectionViewItem id="ek2-AR-oS5" customClass="SensorItem" customModule="Sensors" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="graphContainer" destination="XSC-DH-60t" id="FUo-iJ-Gkw"/>
|
||||
<outlet property="view" destination="c22-O7-iKe" id="W6K-LU-Klf"/>
|
||||
</connections>
|
||||
</collectionViewItem>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSApplicationIcon" width="32" height="32"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -1,335 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="SensorsWindowController" customModule="Sensors" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="arrayController" destination="k4f-4o-be4" id="F6X-Lo-Fc0"/>
|
||||
<outlet property="collectionView" destination="d8j-id-ziA" id="tbm-Yo-sK6"/>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="3Jc-9C-AuF"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Sensors" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="MainWindow" animationBehavior="default" titlebarAppearsTransparent="YES" id="QvC-M9-y7g">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="800" height="515"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1710" height="1069"/>
|
||||
<value key="minSize" type="size" width="800" height="515"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="800" height="515"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<visualEffectView blendingMode="behindWindow" material="underWindowBackground" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="uRj-rz-hcT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="800" height="515"/>
|
||||
<subviews>
|
||||
<scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aKe-JS-2Ui">
|
||||
<rect key="frame" x="20" y="132" width="760" height="353"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="zVN-hJ-YmX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="760" height="353"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<collectionView id="d8j-id-ziA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="760" height="353"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumInteritemSpacing="10" minimumLineSpacing="10" id="jv5-sj-5QH">
|
||||
<size key="itemSize" width="245" height="120"/>
|
||||
</collectionViewFlowLayout>
|
||||
<color key="primaryBackgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<connections>
|
||||
<binding destination="k4f-4o-be4" name="content" keyPath="arrangedObjects" id="WfZ-ms-k8f"/>
|
||||
<binding destination="k4f-4o-be4" name="selectionIndexes" keyPath="selectionIndexes" previousBinding="WfZ-ms-k8f" id="JRi-HO-Ojp"/>
|
||||
<outlet property="dataSource" destination="-2" id="BJq-MM-cYl"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="pbH-A9-JB1">
|
||||
<rect key="frame" x="-100" y="-100" width="233" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="F9Y-Pq-ygs">
|
||||
<rect key="frame" x="744" y="0.0" width="16" height="303"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.data" id="CrI-nj-hKU">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">ArrayIsEmpty</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</scrollView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="X4f-ON-Yh7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="800" height="132"/>
|
||||
<subviews>
|
||||
<searchField wantsLayer="YES" verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0b0-bM-ppa">
|
||||
<rect key="frame" x="20" y="90" width="760" height="22"/>
|
||||
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" usesSingleLineMode="YES" bezelStyle="round" id="m6w-FG-kg5">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.searchText" id="n2O-a4-5b5">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</searchField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CWx-dr-5aC">
|
||||
<rect key="frame" x="18" y="51" width="103" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Temperature" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lZo-Np-2Ev">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showTemperature" id="IqV-HK-3FM"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YH9-KV-isM">
|
||||
<rect key="frame" x="127" y="51" width="72" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Voltage" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="7Kn-WX-eN1">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showVoltage" id="SEA-Tu-BOl"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="DL0-ry-nBa">
|
||||
<rect key="frame" x="205" y="51" width="72" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Current" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="WBA-tr-bDK">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showCurrent" id="McY-1z-eLE"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wh8-P7-8p4">
|
||||
<rect key="frame" x="610" y="52" width="79" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Graph Style:" id="6Ty-8X-UI6">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="b2Z-bC-lIL">
|
||||
<rect key="frame" x="692" y="46" width="92" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Gradient" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="UpT-Zz-emE" id="ToP-qb-kLc">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="bNn-yW-MVT">
|
||||
<items>
|
||||
<menuItem title="Gradient" state="on" id="UpT-Zz-emE"/>
|
||||
<menuItem title="Line" tag="1" id="VP7-OH-4an"/>
|
||||
<menuItem title="Fill" tag="2" id="Uix-Lw-WIT"/>
|
||||
<menuItem title="Bars" tag="3" id="j4P-bQ-osF"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="selectedTag" keyPath="self.graphStyle" id="LYW-IL-Fda"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AZ7-l5-9da">
|
||||
<rect key="frame" x="18" y="21" width="62" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="IOHID" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="B30-xT-MxH">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showIOHID" id="BgH-kZ-wRG"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wQZ-5m-sLD">
|
||||
<rect key="frame" x="86" y="21" width="55" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="SMC" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lBw-Xe-W5E">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showSMC" id="vG2-nh-ynR"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AW4-o1-MSW">
|
||||
<rect key="frame" x="637" y="22" width="52" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Sort by:" id="Zhd-oD-x9y">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YK3-dt-Gbg">
|
||||
<rect key="frame" x="692" y="16" width="92" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Name" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="hmc-dx-TSW" id="zN2-s4-vqC">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="WXZ-C2-QB6">
|
||||
<items>
|
||||
<menuItem title="Name" state="on" id="hmc-dx-TSW"/>
|
||||
<menuItem title="Value" id="Xek-ZI-v6u"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="selectedIndex" keyPath="self.sorting" id="x1p-2T-J5c"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="YK3-dt-Gbg" secondAttribute="bottom" constant="20" symbolic="YES" id="5rr-n1-gE9"/>
|
||||
<constraint firstItem="0b0-bM-ppa" firstAttribute="leading" secondItem="X4f-ON-Yh7" secondAttribute="leading" constant="20" symbolic="YES" id="7Hg-zM-lO0"/>
|
||||
<constraint firstItem="YH9-KV-isM" firstAttribute="centerY" secondItem="CWx-dr-5aC" secondAttribute="centerY" id="DiY-62-WNM"/>
|
||||
<constraint firstItem="AZ7-l5-9da" firstAttribute="leading" secondItem="X4f-ON-Yh7" secondAttribute="leading" constant="20" symbolic="YES" id="Kg6-oj-ya0"/>
|
||||
<constraint firstItem="0b0-bM-ppa" firstAttribute="top" secondItem="X4f-ON-Yh7" secondAttribute="top" constant="20" symbolic="YES" id="MLt-9Q-NWw"/>
|
||||
<constraint firstItem="wQZ-5m-sLD" firstAttribute="leading" secondItem="AZ7-l5-9da" secondAttribute="trailing" constant="8" symbolic="YES" id="TAj-3M-Ri4"/>
|
||||
<constraint firstItem="wh8-P7-8p4" firstAttribute="centerY" secondItem="DL0-ry-nBa" secondAttribute="centerY" id="TS8-6H-T7P"/>
|
||||
<constraint firstItem="DL0-ry-nBa" firstAttribute="centerY" secondItem="YH9-KV-isM" secondAttribute="centerY" id="UFB-Be-d69"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="leading" secondItem="wh8-P7-8p4" secondAttribute="trailing" constant="8" symbolic="YES" id="V4o-Be-jIe"/>
|
||||
<constraint firstItem="AW4-o1-MSW" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="wQZ-5m-sLD" secondAttribute="trailing" constant="8" symbolic="YES" id="YkP-QE-ySV"/>
|
||||
<constraint firstItem="YK3-dt-Gbg" firstAttribute="leading" secondItem="AW4-o1-MSW" secondAttribute="trailing" constant="8" symbolic="YES" id="Yp3-Ns-Xe4"/>
|
||||
<constraint firstItem="wQZ-5m-sLD" firstAttribute="centerY" secondItem="AW4-o1-MSW" secondAttribute="centerY" id="hsM-d4-60o"/>
|
||||
<constraint firstItem="CWx-dr-5aC" firstAttribute="leading" secondItem="X4f-ON-Yh7" secondAttribute="leading" constant="20" symbolic="YES" id="kHN-fy-wU3"/>
|
||||
<constraint firstItem="DL0-ry-nBa" firstAttribute="leading" secondItem="YH9-KV-isM" secondAttribute="trailing" constant="8" symbolic="YES" id="kXC-gz-rYd"/>
|
||||
<constraint firstItem="YK3-dt-Gbg" firstAttribute="width" secondItem="b2Z-bC-lIL" secondAttribute="width" id="loy-q5-zWp"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YK3-dt-Gbg" secondAttribute="trailing" constant="20" symbolic="YES" id="m9H-b7-C5r"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="top" secondItem="0b0-bM-ppa" secondAttribute="bottom" constant="20" symbolic="YES" id="nmc-VG-jfo"/>
|
||||
<constraint firstItem="wh8-P7-8p4" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="DL0-ry-nBa" secondAttribute="trailing" constant="8" symbolic="YES" id="obO-Av-PNp"/>
|
||||
<constraint firstItem="AW4-o1-MSW" firstAttribute="centerY" secondItem="YK3-dt-Gbg" secondAttribute="centerY" id="rQy-7z-w4x"/>
|
||||
<constraint firstItem="YH9-KV-isM" firstAttribute="leading" secondItem="CWx-dr-5aC" secondAttribute="trailing" constant="8" symbolic="YES" id="sOb-Yn-u3A"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0b0-bM-ppa" secondAttribute="trailing" constant="20" symbolic="YES" id="vhy-3U-orM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="b2Z-bC-lIL" secondAttribute="trailing" constant="20" symbolic="YES" id="vmq-Sh-oFu"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="centerY" secondItem="wh8-P7-8p4" secondAttribute="centerY" id="wRu-AK-pi5"/>
|
||||
<constraint firstItem="YK3-dt-Gbg" firstAttribute="top" secondItem="b2Z-bC-lIL" secondAttribute="bottom" constant="10" symbolic="YES" id="ykj-lk-t0n"/>
|
||||
<constraint firstItem="wQZ-5m-sLD" firstAttribute="centerY" secondItem="AZ7-l5-9da" secondAttribute="centerY" id="zw8-PQ-uUL"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.data" id="oYT-Hj-xEu">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">ArrayIsEmpty</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Asg-vC-Nsi">
|
||||
<rect key="frame" x="252" y="69" width="296" height="378"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="yFI-k2-eyH">
|
||||
<rect key="frame" x="20" y="102" width="256" height="256"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="256" id="3bQ-I0-4D7"/>
|
||||
<constraint firstAttribute="width" constant="256" id="wmc-Wj-n9C"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="NSApplicationIcon" id="ccv-7E-1yf"/>
|
||||
</imageView>
|
||||
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="5" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G4l-pP-k1k">
|
||||
<rect key="frame" x="20" y="20" width="256" height="74"/>
|
||||
<subviews>
|
||||
<progressIndicator wantsLayer="YES" maxValue="100" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="Rc4-Fm-hWF">
|
||||
<rect key="frame" x="112" y="42" width="32" height="32"/>
|
||||
<connections>
|
||||
<binding destination="-2" name="animate" keyPath="self.sensors.loading" id="dyi-wq-mTf"/>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.loading" id="OKR-as-1bb">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</progressIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="caY-ih-a0p">
|
||||
<rect key="frame" x="44" y="21" width="168" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="No sensor data available..." id="dA5-eI-Kva">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.loading" id="RA3-Mq-TR1"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="b8F-vc-SdM">
|
||||
<rect key="frame" x="68" y="0.0" width="120" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Reading sensors..." id="ieL-sj-MN9">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.loading" id="R2q-Da-hsc">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<visibilityPriorities>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
</visibilityPriorities>
|
||||
<customSpacing>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
</customSpacing>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="yFI-k2-eyH" firstAttribute="leading" secondItem="Asg-vC-Nsi" secondAttribute="leading" constant="20" symbolic="YES" id="6hv-WO-Mp2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="G4l-pP-k1k" secondAttribute="trailing" constant="20" symbolic="YES" id="Ff2-Ea-C3q"/>
|
||||
<constraint firstItem="G4l-pP-k1k" firstAttribute="top" secondItem="yFI-k2-eyH" secondAttribute="bottom" constant="8" symbolic="YES" id="HJL-Tq-Tud"/>
|
||||
<constraint firstItem="G4l-pP-k1k" firstAttribute="leading" secondItem="Asg-vC-Nsi" secondAttribute="leading" constant="20" symbolic="YES" id="afE-6R-eXF"/>
|
||||
<constraint firstAttribute="bottom" secondItem="G4l-pP-k1k" secondAttribute="bottom" constant="20" symbolic="YES" id="dJQ-em-oKz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="yFI-k2-eyH" secondAttribute="trailing" constant="20" symbolic="YES" id="isW-X4-uYe"/>
|
||||
<constraint firstItem="yFI-k2-eyH" firstAttribute="top" secondItem="Asg-vC-Nsi" secondAttribute="top" constant="20" symbolic="YES" id="woG-6u-Efg"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.data" id="nDO-gY-oWD">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">ArrayIsNotEmpty</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="X4f-ON-Yh7" firstAttribute="top" secondItem="aKe-JS-2Ui" secondAttribute="bottom" id="5IN-cs-jqm"/>
|
||||
<constraint firstItem="Asg-vC-Nsi" firstAttribute="centerX" secondItem="uRj-rz-hcT" secondAttribute="centerX" id="961-zO-gq7"/>
|
||||
<constraint firstItem="aKe-JS-2Ui" firstAttribute="leading" secondItem="uRj-rz-hcT" secondAttribute="leading" constant="20" symbolic="YES" id="K0o-wa-efC"/>
|
||||
<constraint firstAttribute="bottom" secondItem="X4f-ON-Yh7" secondAttribute="bottom" id="L6P-Pp-IP7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="X4f-ON-Yh7" secondAttribute="trailing" id="Lxr-7P-w7M"/>
|
||||
<constraint firstAttribute="trailing" secondItem="aKe-JS-2Ui" secondAttribute="trailing" constant="20" symbolic="YES" id="RZP-rx-Xju"/>
|
||||
<constraint firstItem="aKe-JS-2Ui" firstAttribute="top" secondItem="uRj-rz-hcT" secondAttribute="top" constant="30" id="b5q-1K-Vb2"/>
|
||||
<constraint firstItem="X4f-ON-Yh7" firstAttribute="leading" secondItem="uRj-rz-hcT" secondAttribute="leading" id="ffA-eK-qjQ"/>
|
||||
<constraint firstItem="Asg-vC-Nsi" firstAttribute="centerY" secondItem="uRj-rz-hcT" secondAttribute="centerY" id="hRR-yE-RmG"/>
|
||||
</constraints>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="uRj-rz-hcT" firstAttribute="top" secondItem="EiT-Mj-1SZ" secondAttribute="top" id="WwN-si-Yl6"/>
|
||||
<constraint firstAttribute="trailing" secondItem="uRj-rz-hcT" secondAttribute="trailing" id="eKa-0b-qZ9"/>
|
||||
<constraint firstItem="uRj-rz-hcT" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" id="f7k-yq-eVb"/>
|
||||
<constraint firstAttribute="bottom" secondItem="uRj-rz-hcT" secondAttribute="bottom" id="v4a-ky-3o2"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-110" y="144"/>
|
||||
</window>
|
||||
<arrayController selectsInsertedObjects="NO" avoidsEmptySelection="NO" clearsFilterPredicateOnInsertion="NO" automaticallyRearrangesObjects="YES" id="k4f-4o-be4">
|
||||
<connections>
|
||||
<binding destination="-2" name="contentArray" keyPath="self.sensors.data" id="V1H-EA-tCm"/>
|
||||
</connections>
|
||||
</arrayController>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSApplicationIcon" width="32" height="32"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -1,41 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class Colors
|
||||
{
|
||||
public class func color( for kind: SensorHistoryData.Kind ) -> NSColor
|
||||
{
|
||||
switch kind
|
||||
{
|
||||
case .thermal: return NSColor.systemOrange
|
||||
case .voltage: return NSColor.systemPurple
|
||||
case .current: return NSColor.systemTeal
|
||||
}
|
||||
}
|
||||
|
||||
private init()
|
||||
{}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,47 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public extension NSImage
|
||||
{
|
||||
func tinted( with color: NSColor ) -> NSImage
|
||||
{
|
||||
guard let copy = self.copy() as? NSImage
|
||||
else
|
||||
{
|
||||
return self
|
||||
}
|
||||
|
||||
copy.isTemplate = false
|
||||
let rect = NSRect( origin: NSZeroPoint, size: copy.size )
|
||||
|
||||
copy.lockFocus()
|
||||
color.set()
|
||||
rect.fill( using: .sourceAtop )
|
||||
copy.unlockFocus()
|
||||
|
||||
return copy
|
||||
}
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class SensorGraphView: NSView
|
||||
{
|
||||
@objc
|
||||
public enum GraphStyle: Int
|
||||
{
|
||||
case gradient
|
||||
case line
|
||||
case fill
|
||||
case bars
|
||||
}
|
||||
|
||||
@objc public dynamic var sensor: SensorHistoryData?
|
||||
|
||||
private var defaultsObserver: Any?
|
||||
|
||||
public override init( frame: NSRect )
|
||||
{
|
||||
super.init( frame: frame )
|
||||
|
||||
self.defaultsObserver = NotificationCenter.default.addObserver( forName: UserDefaults.didChangeNotification, object: nil, queue: nil )
|
||||
{
|
||||
[ weak self ] _ in self?.needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
required init?( coder: NSCoder )
|
||||
{
|
||||
super.init( coder: coder )
|
||||
|
||||
self.defaultsObserver = NotificationCenter.default.addObserver( forName: UserDefaults.didChangeNotification, object: nil, queue: nil )
|
||||
{
|
||||
[ weak self ] _ in self?.needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
public override func draw( _ rect: NSRect )
|
||||
{
|
||||
let style = GraphStyle( rawValue: UserDefaults.standard.integer( forKey: "sensorsWindowGraphStyle" ) ) ?? .bars
|
||||
|
||||
self.drawBorder( in: rect, style: style )
|
||||
self.drawBackground( in: rect, style: style )
|
||||
|
||||
guard let sensor = self.sensor, sensor.values.count >= 2
|
||||
else
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
let values = sensor.values.map { CGFloat( $0.doubleValue ) }
|
||||
var min: CGFloat = values.min() ?? 0
|
||||
var max: CGFloat = values.max() ?? 0
|
||||
|
||||
if sensor.kind == .thermal, min >= 0, max <= 100
|
||||
{
|
||||
min = 0
|
||||
max = 100
|
||||
}
|
||||
|
||||
if style == .bars
|
||||
{
|
||||
self.drawBars(
|
||||
in: rect,
|
||||
kind: sensor.kind,
|
||||
values: values,
|
||||
min: min,
|
||||
max: max,
|
||||
color: Colors.color( for: sensor.kind )
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.drawGraph(
|
||||
in: rect.insetBy( dx: 10, dy: 10 ),
|
||||
kind: sensor.kind,
|
||||
values: values,
|
||||
min: min,
|
||||
max: max,
|
||||
color: Colors.color( for: sensor.kind ),
|
||||
style: style
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func drawBorder( in rect: NSRect, style: GraphStyle )
|
||||
{
|
||||
if style == .bars
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
let border = NSBezierPath( roundedRect: rect.insetBy( dx: 1, dy: 1 ), xRadius: 10, yRadius: 10 )
|
||||
border.lineWidth = 1
|
||||
|
||||
NSColor.gray.setStroke()
|
||||
border.stroke()
|
||||
}
|
||||
|
||||
private func drawBackground( in rect: NSRect, style: GraphStyle )
|
||||
{
|
||||
if style == .bars
|
||||
{
|
||||
let c = 15
|
||||
let h = rect.size.height / CGFloat( c )
|
||||
let n = rect.size.width / h
|
||||
|
||||
for i in 0 ..< Int( n )
|
||||
{
|
||||
for j in 0 ..< c
|
||||
{
|
||||
let square = NSRect( x: rect.origin.x + h * CGFloat( i ), y: rect.origin.y + h * CGFloat( j ), width: h, height: h ).insetBy( dx: 1, dy: 1 )
|
||||
|
||||
NSColor.gray.withAlphaComponent( 0.2 ).setFill()
|
||||
square.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let border = NSBezierPath( roundedRect: rect.insetBy( dx: 1, dy: 1 ), xRadius: 10, yRadius: 10 )
|
||||
|
||||
NSColor.gray.withAlphaComponent( 0.2 ).setFill()
|
||||
border.fill()
|
||||
}
|
||||
}
|
||||
|
||||
private func drawGraph( in rect: NSRect, kind: SensorHistoryData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor, style: GraphStyle )
|
||||
{
|
||||
let p1 = NSBezierPath()
|
||||
let p2 = NSBezierPath()
|
||||
p1.lineWidth = 1
|
||||
p2.lineWidth = 0
|
||||
|
||||
if min == max, kind != .thermal
|
||||
{
|
||||
p1.move( to: NSPoint( x: rect.origin.x, y: rect.origin.y + rect.size.height / 2 ) )
|
||||
p1.line( to: NSPoint( x: rect.origin.x + rect.size.width, y: rect.origin.y + rect.size.height / 2 ) )
|
||||
p2.move( to: NSPoint( x: rect.origin.x, y: rect.origin.y + rect.size.height / 2 ) )
|
||||
p2.line( to: NSPoint( x: rect.origin.x + rect.size.width, y: rect.origin.y + rect.size.height / 2 ) )
|
||||
}
|
||||
else
|
||||
{
|
||||
for i in 0 ..< values.count
|
||||
{
|
||||
let value = values[ i ]
|
||||
let dx = rect.size.width / CGFloat( values.count - 1 )
|
||||
let x = rect.origin.x + CGFloat( i ) * dx
|
||||
let v = ( value - min ) / ( max - min )
|
||||
let y = rect.origin.y + v * rect.size.height
|
||||
|
||||
if i == 0
|
||||
{
|
||||
p1.move( to: NSPoint( x: x, y: y ) )
|
||||
p2.move( to: NSPoint( x: x, y: y ) )
|
||||
}
|
||||
else
|
||||
{
|
||||
p1.line( to: NSPoint( x: x, y: y ) )
|
||||
p2.line( to: NSPoint( x: x, y: y ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p2.line( to: NSPoint( x: rect.origin.x + rect.size.width, y: rect.origin.y - 3 ) )
|
||||
p2.line( to: NSPoint( x: rect.origin.x, y: rect.origin.y - 3 ) )
|
||||
p2.close()
|
||||
|
||||
if style == .gradient
|
||||
{
|
||||
let gradient = NSGradient( colors: [ color.withAlphaComponent( 0.25 ), color.withAlphaComponent( 0 ) ] )
|
||||
|
||||
gradient?.draw( in: p2, angle: -90 )
|
||||
}
|
||||
else if style == .fill
|
||||
{
|
||||
color.setFill()
|
||||
p2.fill()
|
||||
}
|
||||
|
||||
color.setStroke()
|
||||
p1.stroke()
|
||||
}
|
||||
|
||||
private func drawBars( in rect: NSRect, kind: SensorHistoryData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor )
|
||||
{
|
||||
let c = 15
|
||||
let h = rect.size.height / CGFloat( c )
|
||||
let n = rect.size.width / h
|
||||
|
||||
let values = Array( values.suffix( Int( n ) ) )
|
||||
|
||||
for i in 0 ..< Int( n )
|
||||
{
|
||||
if i >= values.count
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
let v = values[ i ]
|
||||
let p = ( v - min ) / ( max - min )
|
||||
|
||||
for j in 0 ..< c
|
||||
{
|
||||
if CGFloat( j ) / CGFloat( c ) > p
|
||||
{
|
||||
break
|
||||
}
|
||||
|
||||
let square = NSRect( x: rect.origin.x + h * CGFloat( i ), y: rect.origin.y + h * CGFloat( j ), width: h, height: h ).insetBy( dx: 1, dy: 1 )
|
||||
|
||||
color.setFill()
|
||||
square.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class SensorHistoryData: NSObject, Synchronizable
|
||||
{
|
||||
@objc( SensorHistoryDataKind )
|
||||
public enum Kind: Int, CustomStringConvertible
|
||||
{
|
||||
case thermal
|
||||
case voltage
|
||||
case current
|
||||
|
||||
public var description: String
|
||||
{
|
||||
switch self
|
||||
{
|
||||
case .thermal: return "thermal"
|
||||
case .voltage: return "voltage"
|
||||
case .current: return "current"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc( SensorHistoryDataSource )
|
||||
public enum Source: Int, CustomStringConvertible
|
||||
{
|
||||
case hid
|
||||
case smc
|
||||
|
||||
public var description: String
|
||||
{
|
||||
switch self
|
||||
{
|
||||
case .hid: return "IOHID"
|
||||
case .smc: return "SMC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public private( set ) dynamic var source: Source
|
||||
@objc public private( set ) dynamic var kind: Kind
|
||||
@objc public private( set ) dynamic var name: String
|
||||
|
||||
private var data: [ Double ] = []
|
||||
|
||||
@objc public dynamic var values: [ NSNumber ]
|
||||
{
|
||||
return self.synchronized
|
||||
{
|
||||
return self.data.map { NSNumber( floatLiteral: $0 ) }
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var min: NSNumber?
|
||||
{
|
||||
return self.synchronized
|
||||
{
|
||||
guard let max = self.data.min()
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: max )
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var max: NSNumber?
|
||||
{
|
||||
return self.synchronized
|
||||
{
|
||||
guard let min = self.data.max()
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: min )
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var last: NSNumber?
|
||||
{
|
||||
return self.synchronized
|
||||
{
|
||||
guard let last = self.data.last
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: last )
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public init( source: Source, kind: Kind, name: String )
|
||||
{
|
||||
self.source = source
|
||||
self.kind = kind
|
||||
self.name = name
|
||||
}
|
||||
|
||||
@objc( addValue: )
|
||||
public func add( value: Double )
|
||||
{
|
||||
self.synchronized
|
||||
{
|
||||
var data = self.data
|
||||
|
||||
data.append( value )
|
||||
|
||||
self.data = data.suffix( 50 )
|
||||
|
||||
DispatchQueue.main.async
|
||||
{
|
||||
self.willChangeValue( for: \.values )
|
||||
self.willChangeValue( for: \.min )
|
||||
self.willChangeValue( for: \.max )
|
||||
self.willChangeValue( for: \.last )
|
||||
|
||||
self.didChangeValue( for: \.values )
|
||||
self.didChangeValue( for: \.min )
|
||||
self.didChangeValue( for: \.max )
|
||||
self.didChangeValue( for: \.last )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override var description: String
|
||||
{
|
||||
let min = String( format: "%.2f", self.min?.doubleValue ?? 0 )
|
||||
let max = String( format: "%.2f", self.max?.doubleValue ?? 0 )
|
||||
|
||||
return "\( super.description ): \( self.name ) (\( self.kind ), min: \( min ), max: \( max ))"
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc( SensorIcon )
|
||||
public class SensorIcon: ValueTransformer
|
||||
{
|
||||
public override class func transformedValueClass() -> AnyClass
|
||||
{
|
||||
NSImage.self
|
||||
}
|
||||
|
||||
public override class func allowsReverseTransformation() -> Bool
|
||||
{
|
||||
false
|
||||
}
|
||||
|
||||
public override func transformedValue( _ value: Any? ) -> Any?
|
||||
{
|
||||
guard let data = value as? SensorHistoryData
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
switch data.kind
|
||||
{
|
||||
case .thermal: return NSImage( named: "ThermalTemplate" )?.tinted( with: Colors.color( for: data.kind ) )
|
||||
case .voltage: return NSImage( named: "VoltageTemplate" )?.tinted( with: Colors.color( for: data.kind ) )
|
||||
case .current: return NSImage( named: "CurrentTemplate" )?.tinted( with: Colors.color( for: data.kind ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class SensorItem: NSCollectionViewItem
|
||||
{
|
||||
@objc public dynamic var sensor: SensorHistoryData?
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.graph.sensor = self.sensor
|
||||
}
|
||||
}
|
||||
|
||||
private var graph = SensorGraphView()
|
||||
|
||||
@IBOutlet private var graphContainer: NSView!
|
||||
|
||||
public override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.graph.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.graph.frame = self.graphContainer.bounds
|
||||
|
||||
self.graphContainer.addSubview( self.graph )
|
||||
self.graphContainer.addConstraint( NSLayoutConstraint( item: self.graph, attribute: .width, relatedBy: .equal, toItem: self.graphContainer, attribute: .width, multiplier: 1, constant: 0 ) )
|
||||
self.graphContainer.addConstraint( NSLayoutConstraint( item: self.graph, attribute: .height, relatedBy: .equal, toItem: self.graphContainer, attribute: .height, multiplier: 1, constant: 0 ) )
|
||||
self.graphContainer.addConstraint( NSLayoutConstraint( item: self.graph, attribute: .centerX, relatedBy: .equal, toItem: self.graphContainer, attribute: .centerX, multiplier: 1, constant: 0 ) )
|
||||
self.graphContainer.addConstraint( NSLayoutConstraint( item: self.graph, attribute: .centerY, relatedBy: .equal, toItem: self.graphContainer, attribute: .centerY, multiplier: 1, constant: 0 ) )
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc( SensorValue )
|
||||
public class SensorValue: ValueTransformer
|
||||
{
|
||||
public override class func transformedValueClass() -> AnyClass
|
||||
{
|
||||
NSString.self
|
||||
}
|
||||
|
||||
public override class func allowsReverseTransformation() -> Bool
|
||||
{
|
||||
false
|
||||
}
|
||||
|
||||
public override func transformedValue( _ value: Any? ) -> Any?
|
||||
{
|
||||
guard let n = value as? NSNumber
|
||||
else
|
||||
{
|
||||
return "--"
|
||||
}
|
||||
|
||||
return String( format: "%.02f", n.doubleValue )
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc
|
||||
public class Sensors: NSObject
|
||||
{
|
||||
@objc public private( set ) dynamic var loading = true
|
||||
@objc public private( set ) dynamic var data = [ SensorHistoryData ]()
|
||||
@objc private dynamic var sensors = [ String: SensorHistoryData ]()
|
||||
|
||||
private var shouldRun = true
|
||||
private var completion: ( () -> Void )?
|
||||
|
||||
public override init()
|
||||
{
|
||||
super.init()
|
||||
|
||||
DispatchQueue.global( qos: .background ).async
|
||||
{
|
||||
self.run()
|
||||
}
|
||||
}
|
||||
|
||||
public func stop( completion: ( () -> Void )? )
|
||||
{
|
||||
if self.shouldRun == false
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
self.completion = completion
|
||||
self.shouldRun = false
|
||||
}
|
||||
|
||||
private func run()
|
||||
{
|
||||
let timer = Timer.scheduledTimer( withTimeInterval: 1, repeats: true )
|
||||
{
|
||||
_ in self.readSensors()
|
||||
}
|
||||
|
||||
self.readSensors()
|
||||
RunLoop.current.add( timer, forMode: .default )
|
||||
|
||||
while self.shouldRun
|
||||
{
|
||||
RunLoop.current.run( until: Date( timeIntervalSinceNow: 5 ) )
|
||||
}
|
||||
|
||||
timer.invalidate()
|
||||
|
||||
let completion = self.completion
|
||||
self.completion = nil
|
||||
self.data = []
|
||||
|
||||
completion?()
|
||||
}
|
||||
|
||||
private func readSensors()
|
||||
{
|
||||
self.readIOHIDSensors()
|
||||
self.readSMCSensors()
|
||||
|
||||
let sensors = self.sensors
|
||||
|
||||
DispatchQueue.main.async
|
||||
{
|
||||
self.data = [ SensorHistoryData ]( sensors.values )
|
||||
self.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
private func readIOHIDSensors()
|
||||
{
|
||||
IOHID.shared.readTemperatureSensors().forEach { self.addSensorHistoryData( data: $0, kind: .thermal ) }
|
||||
IOHID.shared.readVoltageSensors().forEach { self.addSensorHistoryData( data: $0, kind: .voltage ) }
|
||||
IOHID.shared.readCurrentSensors().forEach { self.addSensorHistoryData( data: $0, kind: .current ) }
|
||||
}
|
||||
|
||||
private func readSMCSensors()
|
||||
{
|
||||
let all = SMC.shared.readAllKeys()
|
||||
|
||||
all.filter { $0.keyName.hasPrefix( "T" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .thermal ) }
|
||||
all.filter { $0.keyName.hasPrefix( "V" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .voltage ) }
|
||||
all.filter { $0.keyName.hasPrefix( "I" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .current ) }
|
||||
}
|
||||
|
||||
private func addSensorHistoryData( data: IOHIDData, kind: SensorHistoryData.Kind )
|
||||
{
|
||||
let key = String( format: "IOHID.%llu.%@", kind.rawValue, data.name )
|
||||
|
||||
if self.sensors[ key ] == nil
|
||||
{
|
||||
self.sensors[ key ] = SensorHistoryData( source: .hid, kind: kind, name: data.name )
|
||||
}
|
||||
|
||||
self.sensors[ key ]?.add( value: data.value )
|
||||
}
|
||||
|
||||
private func addSensorHistoryData( data: SMCData, kind: SensorHistoryData.Kind )
|
||||
{
|
||||
let value: Double
|
||||
|
||||
if let f = data.value as? Double
|
||||
{
|
||||
value = f
|
||||
}
|
||||
else if let f = data.value as? Float32
|
||||
{
|
||||
value = Double( f )
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
let key = String( format: "SMC.%llu.%@", kind.rawValue, data.keyName )
|
||||
|
||||
if self.sensors[ key ] == nil
|
||||
{
|
||||
self.sensors[ key ] = SensorHistoryData( source: .smc, kind: kind, name: data.keyName )
|
||||
}
|
||||
|
||||
self.sensors[ key ]?.add( value: value )
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class SensorsWindowController: NSWindowController
|
||||
{
|
||||
@objc private dynamic var sensors = Sensors()
|
||||
|
||||
@objc private dynamic var showTemperature = UserDefaults.standard.object( forKey: "sensorsWindowShowTemperature" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showTemperature, forKey: "sensorsWindowShowTemperature" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showVoltage = UserDefaults.standard.object( forKey: "sensorsWindowShowVoltage" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showVoltage, forKey: "sensorsWindowShowVoltage" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showCurrent = UserDefaults.standard.object( forKey: "sensorsWindowShowCurrent" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showCurrent, forKey: "sensorsWindowShowCurrent" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showIOHID = UserDefaults.standard.object( forKey: "sensorsWindowShowIOHID" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showIOHID, forKey: "sensorsWindowShowIOHID" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showSMC = UserDefaults.standard.object( forKey: "sensorsWindowShowSMC" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showSMC, forKey: "sensorsWindowShowSMC" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var sorting = UserDefaults.standard.integer( forKey: "sensorsWindowSorting" )
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.sorting, forKey: "sensorsWindowSorting" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var searchText: String?
|
||||
{
|
||||
didSet { self.updateFilters() }
|
||||
}
|
||||
|
||||
@objc private dynamic var graphStyle = UserDefaults.standard.integer( forKey: "sensorsWindowGraphStyle" )
|
||||
{
|
||||
didSet
|
||||
{
|
||||
UserDefaults.standard.set( self.graphStyle, forKey: "sensorsWindowGraphStyle" )
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet private var collectionView: NSCollectionView!
|
||||
@IBOutlet private var arrayController: NSArrayController!
|
||||
|
||||
public override var windowNibName: NSNib.Name?
|
||||
{
|
||||
"SensorsWindowController"
|
||||
}
|
||||
|
||||
public override func windowDidLoad()
|
||||
{
|
||||
super.windowDidLoad()
|
||||
|
||||
self.arrayController.sortDescriptors = [ NSSortDescriptor( key: "name", ascending: true, selector: #selector( NSString.localizedCaseInsensitiveCompare( _: ) ) ) ]
|
||||
|
||||
self.updateFilters()
|
||||
}
|
||||
|
||||
public func stop( completion: ( () -> Void )? )
|
||||
{
|
||||
self.sensors.stop( completion: completion )
|
||||
}
|
||||
|
||||
private func updateFilters()
|
||||
{
|
||||
var predicates = [ NSPredicate ]()
|
||||
|
||||
if self.showTemperature == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .thermal } )
|
||||
}
|
||||
|
||||
if self.showVoltage == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .voltage } )
|
||||
}
|
||||
|
||||
if self.showCurrent == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .current } )
|
||||
}
|
||||
|
||||
if self.showIOHID == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.source != .hid } )
|
||||
}
|
||||
|
||||
if self.showSMC == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.source != .smc } )
|
||||
}
|
||||
|
||||
if let search = self.searchText, search.count > 0
|
||||
{
|
||||
predicates.append( NSPredicate( format: "name contains[c] %@", search ) )
|
||||
}
|
||||
|
||||
let descriptors =
|
||||
[
|
||||
NSSortDescriptor( key: "name", ascending: true, selector: #selector( NSString.localizedCaseInsensitiveCompare( _: ) ) ),
|
||||
NSSortDescriptor( key: "last", ascending: false ),
|
||||
]
|
||||
|
||||
self.arrayController.sortDescriptors = self.sorting == 1 ? descriptors.reversed() : descriptors
|
||||
|
||||
if predicates.count > 0
|
||||
{
|
||||
self.arrayController.filterPredicate = NSCompoundPredicate( andPredicateWithSubpredicates: predicates )
|
||||
}
|
||||
else
|
||||
{
|
||||
self.arrayController.filterPredicate = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SensorsWindowController: NSCollectionViewDataSource
|
||||
{
|
||||
public func numberOfSections( in collectionView: NSCollectionView ) -> Int
|
||||
{
|
||||
1
|
||||
}
|
||||
|
||||
public func collectionView( _ collectionView: NSCollectionView, numberOfItemsInSection section: Int ) -> Int
|
||||
{
|
||||
( self.arrayController.arrangedObjects as? [ SensorHistoryData ] )?.count ?? 0
|
||||
}
|
||||
|
||||
public func collectionView( _ itemForRepresentedObjectAtcollectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath ) -> NSCollectionViewItem
|
||||
{
|
||||
let item = self.collectionView.makeItem( withIdentifier: NSUserInterfaceItemIdentifier( rawValue: "SensorItem" ), for: indexPath )
|
||||
|
||||
if let item = item as? SensorItem, let sensors = self.arrayController.arrangedObjects as? [ SensorHistoryData ]
|
||||
{
|
||||
if sensors.count > indexPath.item
|
||||
{
|
||||
item.sensor = sensors[ indexPath.item ]
|
||||
}
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol Synchronizable
|
||||
{
|
||||
static func synchronized< T >( closure: () -> T ) -> T
|
||||
|
||||
func synchronized< T >( closure: () -> T ) -> T
|
||||
}
|
||||
|
||||
public extension Synchronizable
|
||||
{
|
||||
static func synchronized< T >( closure: () -> T ) -> T
|
||||
{
|
||||
objc_sync_enter( self )
|
||||
|
||||
let r = closure()
|
||||
|
||||
objc_sync_exit( self )
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func synchronized< T >( closure: () -> T ) -> T
|
||||
{
|
||||
objc_sync_enter( self )
|
||||
|
||||
let r = closure()
|
||||
|
||||
objc_sync_exit( self )
|
||||
|
||||
return r
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
* Copyright (c) 2023, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
@@ -23,6 +23,8 @@
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
import IOHIDKit
|
||||
import SMCKit
|
||||
|
||||
public class ThermalLog: NSObject
|
||||
{
|
||||
|
||||
Submodule Submodules/Sensors updated: c9df3b7dee...87072c683c
Reference in New Issue
Block a user