first commit

This commit is contained in:
David Wernhart
2020-02-16 03:28:55 +01:00
commit 906cec6cc5
80 changed files with 3984 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,596 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
9224A08723F1F70600961AC4 /* com.davidwernhart.Helper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9283741823F1F34400B8AE7A /* com.davidwernhart.Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
927DBFC923F5478E00F8BF0D /* HelperToolProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927DBFC823F5478E00F8BF0D /* HelperToolProtocol.swift */; };
927DBFCA23F5478E00F8BF0D /* HelperToolProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927DBFC823F5478E00F8BF0D /* HelperToolProtocol.swift */; };
9283741B23F1F34400B8AE7A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9283741A23F1F34400B8AE7A /* main.swift */; };
9286FB4923F84C2B00BEB15B /* LaunchAtLogin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9286FB4823F84C2B00BEB15B /* LaunchAtLogin.framework */; };
9286FB4A23F84C2B00BEB15B /* LaunchAtLogin.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9286FB4823F84C2B00BEB15B /* LaunchAtLogin.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
92981EDB23F08D9B00C05424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92981EDA23F08D9B00C05424 /* AppDelegate.swift */; };
92981EDD23F08D9B00C05424 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92981EDC23F08D9B00C05424 /* ContentView.swift */; };
92981EDF23F08D9C00C05424 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 92981EDE23F08D9C00C05424 /* Assets.xcassets */; };
92981EE223F08D9C00C05424 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 92981EE123F08D9C00C05424 /* Preview Assets.xcassets */; };
92981EE523F08D9C00C05424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 92981EE323F08D9C00C05424 /* Main.storyboard */; };
92ACA12B23F5F822003512DC /* HelperTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927DBFCB23F54C2C00F8BF0D /* HelperTool.swift */; };
92ACA12E23F5F861003512DC /* SMC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ACA12D23F5F861003512DC /* SMC.swift */; };
92E24B4123F6DC0D00BE41ED /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92E24B4023F6DC0D00BE41ED /* Helper.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9224A08623F1F6E300961AC4 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
dstPath = Contents/Library/LaunchServices;
dstSubfolderSpec = 1;
files = (
9224A08723F1F70600961AC4 /* com.davidwernhart.Helper in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9258163B23F5CBD500AB7387 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
9283741623F1F34400B8AE7A /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "";
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
9286FB4B23F84C2B00BEB15B /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
9286FB4A23F84C2B00BEB15B /* LaunchAtLogin.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
927DBFC623F533FB00F8BF0D /* Helper-Launchd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Helper-Launchd.plist"; sourceTree = "<group>"; };
927DBFC823F5478E00F8BF0D /* HelperToolProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperToolProtocol.swift; sourceTree = "<group>"; };
927DBFCB23F54C2C00F8BF0D /* HelperTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperTool.swift; sourceTree = "<group>"; };
9283741823F1F34400B8AE7A /* com.davidwernhart.Helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = com.davidwernhart.Helper; sourceTree = BUILT_PRODUCTS_DIR; };
9283741A23F1F34400B8AE7A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
9283741F23F1F38100B8AE7A /* Helper-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Helper-Info.plist"; sourceTree = "<group>"; };
9286FB4823F84C2B00BEB15B /* LaunchAtLogin.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchAtLogin.framework; path = Carthage/Build/Mac/LaunchAtLogin.framework; sourceTree = "<group>"; };
92981ED723F08D9B00C05424 /* AlDente.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AlDente.app; sourceTree = BUILT_PRODUCTS_DIR; };
92981EDA23F08D9B00C05424 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
92981EDC23F08D9B00C05424 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
92981EDE23F08D9C00C05424 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
92981EE123F08D9C00C05424 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
92981EE423F08D9C00C05424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
92981EE623F08D9C00C05424 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
92981EE723F08D9C00C05424 /* AlDente.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AlDente.entitlements; sourceTree = "<group>"; };
92ACA12D23F5F861003512DC /* SMC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMC.swift; sourceTree = "<group>"; };
92E24B4023F6DC0D00BE41ED /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9283741523F1F34400B8AE7A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
92981ED423F08D9B00C05424 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9286FB4923F84C2B00BEB15B /* LaunchAtLogin.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9258163723F5CBD400AB7387 /* Frameworks */ = {
isa = PBXGroup;
children = (
9286FB4823F84C2B00BEB15B /* LaunchAtLogin.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
927DBFC723F545AF00F8BF0D /* Common */ = {
isa = PBXGroup;
children = (
927DBFC823F5478E00F8BF0D /* HelperToolProtocol.swift */,
);
path = Common;
sourceTree = "<group>";
};
9283741923F1F34400B8AE7A /* com.davidwernhart.Helper */ = {
isa = PBXGroup;
children = (
9283741A23F1F34400B8AE7A /* main.swift */,
9283741F23F1F38100B8AE7A /* Helper-Info.plist */,
927DBFC623F533FB00F8BF0D /* Helper-Launchd.plist */,
927DBFCB23F54C2C00F8BF0D /* HelperTool.swift */,
92ACA12D23F5F861003512DC /* SMC.swift */,
);
path = com.davidwernhart.Helper;
sourceTree = "<group>";
};
92981ECE23F08D9B00C05424 = {
isa = PBXGroup;
children = (
927DBFC723F545AF00F8BF0D /* Common */,
92981ED923F08D9B00C05424 /* AlDente */,
9283741923F1F34400B8AE7A /* com.davidwernhart.Helper */,
92981ED823F08D9B00C05424 /* Products */,
9258163723F5CBD400AB7387 /* Frameworks */,
);
sourceTree = "<group>";
};
92981ED823F08D9B00C05424 /* Products */ = {
isa = PBXGroup;
children = (
92981ED723F08D9B00C05424 /* AlDente.app */,
9283741823F1F34400B8AE7A /* com.davidwernhart.Helper */,
);
name = Products;
sourceTree = "<group>";
};
92981ED923F08D9B00C05424 /* AlDente */ = {
isa = PBXGroup;
children = (
92E24B4023F6DC0D00BE41ED /* Helper.swift */,
92981EDA23F08D9B00C05424 /* AppDelegate.swift */,
92981EDC23F08D9B00C05424 /* ContentView.swift */,
92981EDE23F08D9C00C05424 /* Assets.xcassets */,
92981EE323F08D9C00C05424 /* Main.storyboard */,
92981EE623F08D9C00C05424 /* Info.plist */,
92981EE723F08D9C00C05424 /* AlDente.entitlements */,
92981EE023F08D9C00C05424 /* Preview Content */,
);
path = AlDente;
sourceTree = "<group>";
};
92981EE023F08D9C00C05424 /* Preview Content */ = {
isa = PBXGroup;
children = (
92981EE123F08D9C00C05424 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9283741723F1F34400B8AE7A /* com.davidwernhart.Helper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9283741C23F1F34400B8AE7A /* Build configuration list for PBXNativeTarget "com.davidwernhart.Helper" */;
buildPhases = (
9283741423F1F34400B8AE7A /* Sources */,
9283741523F1F34400B8AE7A /* Frameworks */,
9283741623F1F34400B8AE7A /* CopyFiles */,
9258163B23F5CBD500AB7387 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = com.davidwernhart.Helper;
productName = com.davidwernhart.Helper;
productReference = 9283741823F1F34400B8AE7A /* com.davidwernhart.Helper */;
productType = "com.apple.product-type.tool";
};
92981ED623F08D9B00C05424 /* AlDente */ = {
isa = PBXNativeTarget;
buildConfigurationList = 92981EEA23F08D9C00C05424 /* Build configuration list for PBXNativeTarget "AlDente" */;
buildPhases = (
92981ED323F08D9B00C05424 /* Sources */,
92981ED423F08D9B00C05424 /* Frameworks */,
92981ED523F08D9B00C05424 /* Resources */,
9224A08623F1F6E300961AC4 /* CopyFiles */,
92E24B4423F847B500BE41ED /* ShellScript */,
9286FB4B23F84C2B00BEB15B /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = AlDente;
productName = AlDente;
productReference = 92981ED723F08D9B00C05424 /* AlDente.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
92981ECF23F08D9B00C05424 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1130;
LastUpgradeCheck = 1130;
ORGANIZATIONNAME = "David Wernhart";
TargetAttributes = {
9283741723F1F34400B8AE7A = {
CreatedOnToolsVersion = 11.3.1;
};
92981ED623F08D9B00C05424 = {
CreatedOnToolsVersion = 11.3.1;
};
};
};
buildConfigurationList = 92981ED223F08D9B00C05424 /* Build configuration list for PBXProject "AlDente" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 92981ECE23F08D9B00C05424;
productRefGroup = 92981ED823F08D9B00C05424 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
92981ED623F08D9B00C05424 /* AlDente */,
9283741723F1F34400B8AE7A /* com.davidwernhart.Helper */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
92981ED523F08D9B00C05424 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
92981EE523F08D9C00C05424 /* Main.storyboard in Resources */,
92981EE223F08D9C00C05424 /* Preview Assets.xcassets in Resources */,
92981EDF23F08D9C00C05424 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
92E24B4423F847B500BE41ED /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "${PROJECT_DIR}/Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9283741423F1F34400B8AE7A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9283741B23F1F34400B8AE7A /* main.swift in Sources */,
92ACA12B23F5F822003512DC /* HelperTool.swift in Sources */,
927DBFCA23F5478E00F8BF0D /* HelperToolProtocol.swift in Sources */,
92ACA12E23F5F861003512DC /* SMC.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
92981ED323F08D9B00C05424 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
927DBFC923F5478E00F8BF0D /* HelperToolProtocol.swift in Sources */,
92981EDD23F08D9B00C05424 /* ContentView.swift in Sources */,
92981EDB23F08D9B00C05424 /* AppDelegate.swift in Sources */,
92E24B4123F6DC0D00BE41ED /* Helper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
92981EE323F08D9C00C05424 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
92981EE423F08D9C00C05424 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
9283741D23F1F34400B8AE7A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2.0;
DEVELOPMENT_TEAM = 56C2L92EKW;
ENABLE_HARDENED_RUNTIME = YES;
"FRAMEWORK_SEARCH_PATHS[arch=*]" = "$(PROJECT_DIR)/Frameworks";
INFOPLIST_FILE = "com.davidwernhart.Helper/Helper-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0;
OTHER_LDFLAGS = (
"-sectcreate",
__TEXT,
__info_plist,
"$(SRCROOT)/com.davidwernhart.Helper/Helper-Info.plist",
"-sectcreate",
__TEXT,
__launchd_plist,
"$(SRCROOT)/com.davidwernhart.Helper/Helper-Launchd.plist",
);
PRODUCT_BUNDLE_IDENTIFIER = com.davidwernhart.Helper;
PRODUCT_MODULE_NAME = AlDenteHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Frameworks";
};
name = Debug;
};
9283741E23F1F34400B8AE7A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2.0;
DEVELOPMENT_TEAM = 56C2L92EKW;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "com.davidwernhart.Helper/Helper-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0;
OTHER_LDFLAGS = (
"-sectcreate",
__TEXT,
__info_plist,
"$(SRCROOT)/com.davidwernhart.Helper/Helper-Info.plist",
"-sectcreate",
__TEXT,
__launchd_plist,
"$(SRCROOT)/com.davidwernhart.Helper/Helper-Launchd.plist",
);
PRODUCT_BUNDLE_IDENTIFIER = com.davidwernhart.Helper;
PRODUCT_MODULE_NAME = AlDenteHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Frameworks";
};
name = Release;
};
92981EE823F08D9C00C05424 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
92981EE923F08D9C00C05424 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
};
92981EEB23F08D9C00C05424 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AlDente/AlDente.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AlDente/Preview Content\"";
DEVELOPMENT_TEAM = 56C2L92EKW;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = AlDente/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.davidwernhart.AlDente;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
92981EEC23F08D9C00C05424 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AlDente/AlDente.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AlDente/Preview Content\"";
DEVELOPMENT_TEAM = 56C2L92EKW;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = AlDente/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.davidwernhart.AlDente;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9283741C23F1F34400B8AE7A /* Build configuration list for PBXNativeTarget "com.davidwernhart.Helper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9283741D23F1F34400B8AE7A /* Debug */,
9283741E23F1F34400B8AE7A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
92981ED223F08D9B00C05424 /* Build configuration list for PBXProject "AlDente" */ = {
isa = XCConfigurationList;
buildConfigurations = (
92981EE823F08D9C00C05424 /* Debug */,
92981EE923F08D9C00C05424 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
92981EEA23F08D9C00C05424 /* Build configuration list for PBXNativeTarget "AlDente" */ = {
isa = XCConfigurationList;
buildConfigurations = (
92981EEB23F08D9C00C05424 /* Debug */,
92981EEC23F08D9C00C05424 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 92981ECF23F08D9B00C05424 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:AlDente.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>AlDente.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>Hall.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>Helper.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>com.davidwernhart.Helper.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
</dict>
</plist>

BIN
AlDente/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.files.user-selected.read-only</key>
<false/>
</dict>
</plist>

64
AlDente/AppDelegate.swift Normal file
View File

@@ -0,0 +1,64 @@
//
// AppDelegate.swift
// AlDente
//
// Created by David Wernhart on 09.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import Cocoa
import SwiftUI
import ServiceManagement
import Foundation
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
//var window: NSWindow!
var statusBarItem: NSStatusItem!
var popover: NSPopover!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
// Create the popover
let popover = NSPopover()
popover.contentSize = NSSize(width: 400, height: 600)
popover.behavior = .transient
popover.contentViewController = NSHostingController(rootView: contentView)
self.popover = popover
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = "🍝"
if let button = self.statusBarItem.button {
button.action = #selector(togglePopover(_:))
}
Helper.instance.checkHelperVersion()
}
@objc func togglePopover(_ sender: AnyObject?) {
self.popover.contentViewController?.view.window?.becomeKey()
if let button = self.statusBarItem.button {
if self.popover.isShown {
self.popover.performClose(sender)
} else {
self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}

BIN
AlDente/Assets.xcassets/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,61 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "spaghetti-2.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "spaghetti-1.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "spaghetti.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,56 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
},
"colors" : [
{
"idiom" : "universal",
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "1.000",
"alpha" : "1.000",
"blue" : "1.000",
"green" : "1.000"
}
}
},
{
"idiom" : "universal",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "light"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "0.800",
"alpha" : "1.000",
"blue" : "0.800",
"green" : "0.800"
}
}
},
{
"idiom" : "universal",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "0.100",
"alpha" : "1.000",
"blue" : "0.100",
"green" : "0.100"
}
}
}
]
}

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="AlDente" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="AlDente" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About AlDente" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide AlDente" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit AlDente" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="AlDente" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
</scenes>
</document>

213
AlDente/ContentView.swift Normal file
View File

@@ -0,0 +1,213 @@
//
// ContentView.swift
// AlDente
//
// Created by David Wernhart on 09.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import SwiftUI
import ServiceManagement
import Foundation
import LaunchAtLogin
import Combine
struct BlueButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.foregroundColor(configuration.isPressed ? Color.blue : Color.white)
.background(configuration.isPressed ? Color.white : Color.blue)
.cornerRadius(6.0)
.padding()
}
}
struct RedButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.foregroundColor(configuration.isPressed ? Color.red : Color.white)
.background(configuration.isPressed ? Color.white : Color.red)
.cornerRadius(6.0)
.padding()
}
}
struct settings<Content: View>: View {
var content: () -> Content
@State var launchOnLogin = LaunchAtLogin.isEnabled
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content
//Helper.instance.delegate = self
}
var body: some View {
VStack(alignment: .center){
HStack(alignment: .center) {
Toggle(isOn: Binding(
get: {
self.launchOnLogin
},
set: {(newValue) in
self.launchOnLogin = newValue
if(newValue){
print("launch on login turned on!")
LaunchAtLogin.isEnabled = true
}
else{
print("launch on login turned off!")
LaunchAtLogin.isEnabled = false
}
}
)) {
Text("Launch on Login")
}.padding()
Spacer()
Button( action: {
Helper.instance.installHelper()
}
) {
Text("Reinstall Helper")
.frame(maxWidth: 120, maxHeight: 30)
}.buttonStyle(BlueButtonStyle())
}
HStack(alignment: .center) {
Spacer()
VStack(alignment: .leading){
Text("AlDente 🍝").font(.subheadline)
Text("github.com/davidwernhart/AlDente").foregroundColor(Color.blue)
Text("Created with 🤍 by David Wernhart in 2020")
// Text("AlDente 🍝").font(.title)
// Text("Keep your battery just right").font(.subheadline)
}
Spacer()
Button(action: {
let url = URL(string: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6PLR7D9ZCZGGC&source=url")!
if NSWorkspace.shared.open(url) {
print("default browser was successfully opened")
}
}) {
Text("Donate")
.frame(maxWidth: 60, maxHeight: 50)
}
.buttonStyle(BlueButtonStyle())
}
}.background(Color("SettingsColor")).cornerRadius(5)
}
}
struct ContentView: View{
@State var adaptableHeight = CGFloat(100)
@State var showSettings = false
@ObservedObject var presenter = SMCPresenter()
init() {
Helper.instance.delegate = presenter
Helper.instance.readMaxBatteryCharge()
}
var body: some View {
let vstack = VStack{
VStack(alignment: .leading) {
//Text("Value is: \(presenter.value)")
HStack(alignment: .center){
Text(" Max. Battery Charge:").padding(.leading)
TextField("Number", value: Binding(
get: {
Float(self.presenter.value)
},
set: {(newValue) in
if(newValue >= 20 && newValue <= 100){
self.presenter.setValue(value: newValue)
}
}
), formatter: NumberFormatter())
.multilineTextAlignment(.center)
.frame(maxWidth:50)
.textFieldStyle(RoundedBorderTextFieldStyle())
Spacer()
Button( action: {
self.showSettings = !self.showSettings
if(self.showSettings){
self.adaptableHeight = 235
}
else{
self.adaptableHeight = 100
}
}) {
Text("Settings")
.frame(maxWidth: 70, maxHeight: 30)
}.buttonStyle(BlueButtonStyle()).padding(.leading,-30)
Button( action: {
NSApplication.shared.terminate(self)
}) {
Text("Exit")
.frame(maxWidth: 50, maxHeight: 30)
}.buttonStyle(RedButtonStyle()).padding(.leading,-30)
}
HStack(alignment: .center){
Slider(value: Binding(
get: {
Float(self.presenter.value)
},
set: {(newValue) in
if(newValue >= 20 && newValue <= 100){
self.presenter.setValue(value: newValue)
}
}
), in: 20...100).padding(.horizontal).padding(.top,-20)
}
Spacer()
if(self.showSettings){
settings{Text("")}
}
}.frame(width: 400, height: adaptableHeight)
}
return vstack
}
}
class SMCPresenter: ObservableObject, HelperDelegate{
@Published var value: UInt8 = 0
private var timer: Timer?
func OnMaxBatRead(value: UInt8){
DispatchQueue.main.async {
self.value = value
}
}
func setValue(value: Float){
DispatchQueue.main.async {
self.value = UInt8(value)
}
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { timer in
print("Setting Max Battery To: ",value)
Helper.instance.writeMaxBatteryCharge(setVal: UInt8(value))
Helper.instance.readMaxBatteryCharge()
self.timer = nil
})
}
}

124
AlDente/Helper.swift Normal file
View File

@@ -0,0 +1,124 @@
//
// Helper.swift
// AlDente
//
// Created by David Wernhart on 14.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import Cocoa
import SwiftUI
import ServiceManagement
import Foundation
protocol HelperDelegate {
func OnMaxBatRead(value: UInt8)
}
class Helper{
static let instance = Helper()
public var delegate: HelperDelegate?
// var receiveMessage = "" {
// didSet {
// DispatchQueue.main.async {
// print(self.receiveMessage)
// // if self.receiveMessage.isEmpty {
// // self.clearButton.isEnabled = false
// // } else {
// // self.clearButton.isEnabled = true
// // }
// }
// }
// }
lazy var helperToolConnection: NSXPCConnection = {
let connection = NSXPCConnection(machServiceName: "com.davidwernhart.Helper.mach", options: .privileged)
connection.remoteObjectInterface = NSXPCInterface(with: HelperToolProtocol.self)
connection.resume()
return connection
}()
@objc func installHelper() {
print("trying to install helper!")
var status: OSStatus = noErr
let helperID = "com.davidwernhart.Helper" as CFString//Prefs.helperID as CFString
var authItem = AuthorizationItem(name: kSMRightBlessPrivilegedHelper, valueLength: 0, value: nil, flags: 0)
var authRights = AuthorizationRights(count: 1, items: &authItem)
let authFlags: AuthorizationFlags = [.interactionAllowed, .preAuthorize, .extendRights]
var authRef: AuthorizationRef? = nil
status = AuthorizationCreate(&authRights, nil, authFlags, &authRef)
if status != errAuthorizationSuccess {
print(SecCopyErrorMessageString(status,nil))
print("Error:", String(status))
}
var error: Unmanaged<CFError>? = nil
SMJobBless(kSMDomainSystemLaunchd, helperID, authRef, &error)
if let e = error?.takeRetainedValue() {
print("Domain:", CFErrorGetDomain(e))
print("Code:", CFErrorGetCode(e))
print("UserInfo:", CFErrorCopyUserInfo(e))
print("Description:", CFErrorCopyDescription(e))
print("Reason:", CFErrorCopyFailureReason(e))
print("Suggestion:", CFErrorCopyRecoverySuggestion(e))
}
}
@objc func writeMaxBatteryCharge(setVal: UInt8){
SMCWriteByte(key: "BCLM", value: setVal)
}
@objc func readMaxBatteryCharge(){
SMCReadByte(key:"BCLM",withReply: { (value) in
print(String(value))
self.delegate?.OnMaxBatRead(value: value)
})
}
@objc func checkHelperVersion() {
print("checking helper version")
if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
let e = error as NSError
print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
self.installHelper()
//self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
}) as? HelperToolProtocol {
helper.getVersion(withReply: { (version) in
print("helperVersion:", helperVersion, " version from helper:",version)
if(!helperVersion.elementsEqual(version)){
self.installHelper()
}
//self.receiveMessage.append("Version: \(version)\n")
})
}
}
@objc func SMCReadByte(key:String, withReply reply: @escaping (UInt8) -> Void){
if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
let e = error as NSError
print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
//self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
}) as? HelperToolProtocol {
helper.readSMCByte(key: key) { (value) in
reply (value)
}
}
}
@objc func SMCWriteByte(key:String,value:UInt8){
if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
let e = error as NSError
print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
//self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
}) as? HelperToolProtocol {
helper.setSMCByte(key: key,value: value)
}
}
}

43
AlDente/Info.plist Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<false/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 David Wernhart. All rights reserved.</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
<key>SMPrivilegedExecutables</key>
<dict>
<key>com.davidwernhart.Helper</key>
<string>identifier &quot;com.davidwernhart.Helper&quot; and anchor apple generic and certificate leaf[subject.CN] = &quot;Apple Development: david.wernhart96@gmail.com (GSDX9BQ584)&quot; and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

2
Cartfile Normal file
View File

@@ -0,0 +1,2 @@
github "sindresorhus/LaunchAtLogin"

1
Cartfile.resolved Normal file
View File

@@ -0,0 +1 @@
github "sindresorhus/LaunchAtLogin" "v3.0.0"

BIN
Carthage/.DS_Store vendored Normal file

Binary file not shown.

BIN
Carthage/Build/.DS_Store generated vendored Normal file

Binary file not shown.

19
Carthage/Build/.LaunchAtLogin.version generated vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"Mac" : [
{
"name" : "LaunchAtLogin",
"hash" : "3aa89276b3b2caf4499607f2f8edc08acaa6b1ea55a5e9b42f7ca47c595f41d1",
"swiftToolchainVersion" : "5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)"
}
],
"watchOS" : [
],
"tvOS" : [
],
"commitish" : "v3.0.0",
"iOS" : [
]
}

BIN
Carthage/Build/Mac/.DS_Store generated vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.com.sindresorhus.LaunchAtLogin</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>3.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

1
Carthage/Build/Mac/LaunchAtLogin.framework/Headers generated vendored Symbolic link
View File

@@ -0,0 +1 @@
Versions/Current/Headers

View File

@@ -0,0 +1 @@
Versions/Current/LaunchAtLogin

1
Carthage/Build/Mac/LaunchAtLogin.framework/Modules generated vendored Symbolic link
View File

@@ -0,0 +1 @@
Versions/Current/Modules

1
Carthage/Build/Mac/LaunchAtLogin.framework/Resources generated vendored Symbolic link
View File

@@ -0,0 +1 @@
Versions/Current/Resources

View File

@@ -0,0 +1,204 @@
// Generated by Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif
#if __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif
#pragma clang diagnostic ignored "-Wauto-import"
#include <Foundation/Foundation.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if __has_include(<uchar.h>)
# include <uchar.h>
# elif !defined(__cplusplus)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#endif
#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
# define SWIFT_CLASS_PROPERTY(...)
# endif
#endif
#if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#endif
#if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#endif
#if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#endif
#if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define SWIFT_WARN_UNUSED_RESULT
#endif
#if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
#else
# define SWIFT_NORETURN
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_RESILIENT_CLASS)
# if __has_attribute(objc_class_stub)
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
# else
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif
#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif
#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
# define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# if __has_feature(generalized_swift_name)
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# else
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if !defined(SWIFT_UNAVAILABLE_MSG)
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
#endif
#if !defined(SWIFT_AVAILABILITY)
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
#endif
#if !defined(SWIFT_WEAK_IMPORT)
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#endif
#if !defined(SWIFT_DEPRECATED)
# define SWIFT_DEPRECATED __attribute__((deprecated))
#endif
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
#else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
#endif
#if !defined(IBSegueAction)
# define IBSegueAction
#endif
#if __has_feature(modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
#endif
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
#if __has_warning("-Wpragma-clang-attribute")
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wnullability"
#if __has_attribute(external_source_symbol)
# pragma push_macro("any")
# undef any
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="LaunchAtLogin",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
# pragma pop_macro("any")
#endif
#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,4 @@
#import <Cocoa/Cocoa.h>
FOUNDATION_EXPORT double LaunchAtLoginVersionNumber;
FOUNDATION_EXPORT const unsigned char LaunchAtLoginVersionString[];

Binary file not shown.

View File

@@ -0,0 +1,11 @@
framework module LaunchAtLogin {
umbrella header "LaunchAtLogin.h"
export *
module * { export * }
}
module LaunchAtLogin.Swift {
header "LaunchAtLogin-Swift.h"
requires objc
}

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>19D76</string>
<key>CFBundleExecutable</key>
<string>LaunchAtLogin</string>
<key>CFBundleIdentifier</key>
<string>com.sindresorhus.LaunchAtLogin</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>LaunchAtLogin</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.0.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11C504</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19B90</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1130</string>
<key>DTXcodeBuild</key>
<string>11C504</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
</dict>
</plist>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>19D76</string>
<key>CFBundleExecutable</key>
<string>LaunchAtLoginHelper</string>
<key>CFBundleIdentifier</key>
<string>com.sindresorhus.LaunchAtLoginHelper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>LaunchAtLoginHelper</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11C504</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19B90</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1130</string>
<key>DTXcodeBuild</key>
<string>11C504</string>
<key>LSBackgroundOnly</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1,22 @@
#!/bin/bash
origin_helper_path="$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/LaunchAtLogin.framework/Resources/LaunchAtLoginHelper.app"
helper_dir="$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems"
helper_path="$helper_dir/LaunchAtLoginHelper.app"
rm -rf "$helper_path"
mkdir -p "$helper_dir"
cp -rf "$origin_helper_path" "$helper_dir/"
defaults write "$helper_path/Contents/Info" CFBundleIdentifier -string "$PRODUCT_BUNDLE_IDENTIFIER-LaunchAtLoginHelper"
if [[ -n $CODE_SIGN_ENTITLEMENTS ]]; then
codesign --force --entitlements="$CODE_SIGN_ENTITLEMENTS" --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
else
codesign --force --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
fi
if [[ $CONFIGURATION == "Release" ]]; then
rm -rf "$origin_helper_path"
rm "$(dirname "$origin_helper_path")/copy-helper.sh"
fi

View File

@@ -0,0 +1 @@
A

View File

@@ -0,0 +1,8 @@
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1 @@
* text=auto eol=lf

View File

@@ -0,0 +1,4 @@
github: sindresorhus
open_collective: sindresorhus
patreon: sindresorhus
custom: https://sindresorhus.com/donate

View File

@@ -0,0 +1,2 @@
xcuserdata
project.xcworkspace

View File

@@ -0,0 +1,494 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
E32E9B681EB87D7B000FEEE9 /* LaunchAtLogin.h in Headers */ = {isa = PBXBuildFile; fileRef = E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */; settings = {ATTRIBUTES = (Public, ); }; };
E32E9B6F1EB87DC5000FEEE9 /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */; };
E32E9B771EB87EA3000FEEE9 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32E9B761EB87EA3000FEEE9 /* main.swift */; };
E32E9B861EB8845E000FEEE9 /* LaunchAtLoginHelper.app in Resources */ = {isa = PBXBuildFile; fileRef = E32E9B741EB87EA3000FEEE9 /* LaunchAtLoginHelper.app */; };
E32E9B931EB889AE000FEEE9 /* copy-helper.sh in Resources */ = {isa = PBXBuildFile; fileRef = E32E9B921EB889AE000FEEE9 /* copy-helper.sh */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
E32E9B871EB88462000FEEE9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E32E9B5A1EB87D7B000FEEE9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = E32E9B731EB87EA3000FEEE9;
remoteInfo = LaunchAtLoginHelper;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
E32E9B631EB87D7B000FEEE9 /* LaunchAtLogin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LaunchAtLogin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LaunchAtLogin.h; sourceTree = "<group>"; usesTabs = 1; };
E32E9B671EB87D7B000FEEE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = LaunchAtLogin.swift; sourceTree = "<group>"; usesTabs = 1; };
E32E9B741EB87EA3000FEEE9 /* LaunchAtLoginHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LaunchAtLoginHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };
E32E9B761EB87EA3000FEEE9 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = main.swift; sourceTree = "<group>"; usesTabs = 1; };
E32E9B7F1EB87EA3000FEEE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E32E9B921EB889AE000FEEE9 /* copy-helper.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = "copy-helper.sh"; sourceTree = "<group>"; usesTabs = 1; };
E3B8C38A20C0003300272EC0 /* LaunchAtLoginHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LaunchAtLoginHelper.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E32E9B5F1EB87D7B000FEEE9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E32E9B711EB87EA3000FEEE9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E32E9B591EB87D7B000FEEE9 = {
isa = PBXGroup;
children = (
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */,
E32E9B751EB87EA3000FEEE9 /* LaunchAtLoginHelper */,
E32E9B641EB87D7B000FEEE9 /* Products */,
);
sourceTree = "<group>";
usesTabs = 1;
};
E32E9B641EB87D7B000FEEE9 /* Products */ = {
isa = PBXGroup;
children = (
E32E9B631EB87D7B000FEEE9 /* LaunchAtLogin.framework */,
E32E9B741EB87EA3000FEEE9 /* LaunchAtLoginHelper.app */,
);
name = Products;
sourceTree = "<group>";
};
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */ = {
isa = PBXGroup;
children = (
E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */,
E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */,
E32E9B921EB889AE000FEEE9 /* copy-helper.sh */,
E32E9B671EB87D7B000FEEE9 /* Info.plist */,
);
path = LaunchAtLogin;
sourceTree = "<group>";
};
E32E9B751EB87EA3000FEEE9 /* LaunchAtLoginHelper */ = {
isa = PBXGroup;
children = (
E32E9B761EB87EA3000FEEE9 /* main.swift */,
E32E9B7F1EB87EA3000FEEE9 /* Info.plist */,
E3B8C38A20C0003300272EC0 /* LaunchAtLoginHelper.entitlements */,
);
path = LaunchAtLoginHelper;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
E32E9B601EB87D7B000FEEE9 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
E32E9B681EB87D7B000FEEE9 /* LaunchAtLogin.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
E32E9B621EB87D7B000FEEE9 /* LaunchAtLogin */ = {
isa = PBXNativeTarget;
buildConfigurationList = E32E9B6B1EB87D7B000FEEE9 /* Build configuration list for PBXNativeTarget "LaunchAtLogin" */;
buildPhases = (
E32E9B5E1EB87D7B000FEEE9 /* Sources */,
E32E9B5F1EB87D7B000FEEE9 /* Frameworks */,
E32E9B601EB87D7B000FEEE9 /* Headers */,
E32E9B611EB87D7B000FEEE9 /* Resources */,
);
buildRules = (
);
dependencies = (
E32E9B881EB88462000FEEE9 /* PBXTargetDependency */,
);
name = LaunchAtLogin;
productName = LaunchAtLogin;
productReference = E32E9B631EB87D7B000FEEE9 /* LaunchAtLogin.framework */;
productType = "com.apple.product-type.framework";
};
E32E9B731EB87EA3000FEEE9 /* LaunchAtLoginHelper */ = {
isa = PBXNativeTarget;
buildConfigurationList = E32E9B801EB87EA3000FEEE9 /* Build configuration list for PBXNativeTarget "LaunchAtLoginHelper" */;
buildPhases = (
E32E9B701EB87EA3000FEEE9 /* Sources */,
E32E9B711EB87EA3000FEEE9 /* Frameworks */,
E32E9B721EB87EA3000FEEE9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = LaunchAtLoginHelper;
productName = LaunchAtLoginHelper;
productReference = E32E9B741EB87EA3000FEEE9 /* LaunchAtLoginHelper.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E32E9B5A1EB87D7B000FEEE9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Sindre Sorhus";
TargetAttributes = {
E32E9B621EB87D7B000FEEE9 = {
CreatedOnToolsVersion = 8.3.2;
LastSwiftMigration = 1020;
};
E32E9B731EB87EA3000FEEE9 = {
CreatedOnToolsVersion = 8.3.2;
LastSwiftMigration = 1020;
SystemCapabilities = {
com.apple.HardenedRuntime = {
enabled = 1;
};
com.apple.Sandbox = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = E32E9B5D1EB87D7B000FEEE9 /* Build configuration list for PBXProject "LaunchAtLogin" */;
compatibilityVersion = "Xcode 11.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E32E9B591EB87D7B000FEEE9;
productRefGroup = E32E9B641EB87D7B000FEEE9 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E32E9B621EB87D7B000FEEE9 /* LaunchAtLogin */,
E32E9B731EB87EA3000FEEE9 /* LaunchAtLoginHelper */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E32E9B611EB87D7B000FEEE9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E32E9B861EB8845E000FEEE9 /* LaunchAtLoginHelper.app in Resources */,
E32E9B931EB889AE000FEEE9 /* copy-helper.sh in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E32E9B721EB87EA3000FEEE9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E32E9B5E1EB87D7B000FEEE9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E32E9B6F1EB87DC5000FEEE9 /* LaunchAtLogin.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E32E9B701EB87EA3000FEEE9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E32E9B771EB87EA3000FEEE9 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E32E9B881EB88462000FEEE9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E32E9B731EB87EA3000FEEE9 /* LaunchAtLoginHelper */;
targetProxy = E32E9B871EB88462000FEEE9 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
E32E9B691EB87D7B000FEEE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VALID_ARCHS = x86_64;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
E32E9B6A1EB87D7B000FEEE9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
VALID_ARCHS = x86_64;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
E32E9B6C1EB87D7B000FEEE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = LaunchAtLogin/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 3.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLogin;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
E32E9B6D1EB87D7B000FEEE9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = LaunchAtLogin/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 3.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLogin;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
E32E9B811EB87EA3000FEEE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLoginHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Debug;
};
E32E9B821EB87EA3000FEEE9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLoginHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E32E9B5D1EB87D7B000FEEE9 /* Build configuration list for PBXProject "LaunchAtLogin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E32E9B691EB87D7B000FEEE9 /* Debug */,
E32E9B6A1EB87D7B000FEEE9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E32E9B6B1EB87D7B000FEEE9 /* Build configuration list for PBXNativeTarget "LaunchAtLogin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E32E9B6C1EB87D7B000FEEE9 /* Debug */,
E32E9B6D1EB87D7B000FEEE9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E32E9B801EB87EA3000FEEE9 /* Build configuration list for PBXNativeTarget "LaunchAtLoginHelper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E32E9B811EB87EA3000FEEE9 /* Debug */,
E32E9B821EB87EA3000FEEE9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E32E9B5A1EB87D7B000FEEE9 /* Project object */;
}

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B621EB87D7B000FEEE9"
BuildableName = "LaunchAtLogin.framework"
BlueprintName = "LaunchAtLogin"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B621EB87D7B000FEEE9"
BuildableName = "LaunchAtLogin.framework"
BlueprintName = "LaunchAtLogin"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B621EB87D7B000FEEE9"
BuildableName = "LaunchAtLogin.framework"
BlueprintName = "LaunchAtLogin"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B731EB87EA3000FEEE9"
BuildableName = "LaunchAtLoginHelper.app"
BlueprintName = "LaunchAtLoginHelper"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B731EB87EA3000FEEE9"
BuildableName = "LaunchAtLoginHelper.app"
BlueprintName = "LaunchAtLoginHelper"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B731EB87EA3000FEEE9"
BuildableName = "LaunchAtLoginHelper.app"
BlueprintName = "LaunchAtLoginHelper"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E32E9B731EB87EA3000FEEE9"
BuildableName = "LaunchAtLoginHelper.app"
BlueprintName = "LaunchAtLoginHelper"
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
</dict>
</plist>

View File

@@ -0,0 +1,4 @@
#import <Cocoa/Cocoa.h>
FOUNDATION_EXPORT double LaunchAtLoginVersionNumber;
FOUNDATION_EXPORT const unsigned char LaunchAtLoginVersionString[];

View File

@@ -0,0 +1,21 @@
import Foundation
import ServiceManagement
public struct LaunchAtLogin {
private static let id = "\(Bundle.main.bundleIdentifier!)-LaunchAtLoginHelper"
public static var isEnabled: Bool {
get {
guard let jobs = (SMCopyAllJobDictionaries(kSMDomainUserLaunchd).takeRetainedValue() as? [[String: AnyObject]]) else {
return false
}
let job = jobs.first { $0["Label"] as! String == id }
return job?["OnDemand"] as? Bool ?? false
}
set {
SMLoginItemSetEnabled(id as CFString, newValue)
}
}
}

View File

@@ -0,0 +1,22 @@
#!/bin/bash
origin_helper_path="$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/LaunchAtLogin.framework/Resources/LaunchAtLoginHelper.app"
helper_dir="$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems"
helper_path="$helper_dir/LaunchAtLoginHelper.app"
rm -rf "$helper_path"
mkdir -p "$helper_dir"
cp -rf "$origin_helper_path" "$helper_dir/"
defaults write "$helper_path/Contents/Info" CFBundleIdentifier -string "$PRODUCT_BUNDLE_IDENTIFIER-LaunchAtLoginHelper"
if [[ -n $CODE_SIGN_ENTITLEMENTS ]]; then
codesign --force --entitlements="$CODE_SIGN_ENTITLEMENTS" --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
else
codesign --force --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
fi
if [[ $CONFIGURATION == "Release" ]]; then
rm -rf "$origin_helper_path"
rm "$(dirname "$origin_helper_path")/copy-helper.sh"
fi

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
<key>LSBackgroundOnly</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,25 @@
import Cocoa
final class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
let bundleId = Bundle.main.bundleIdentifier!
// TODO: Make this more strict by only replacing at the end
let mainBundleId = bundleId.replacingOccurrences(of: "-LaunchAtLoginHelper", with: "")
// Ensure the app is not already running
guard NSRunningApplication.runningApplications(withBundleIdentifier: mainBundleId).isEmpty else {
NSApp.terminate(nil)
return
}
let pathComponents = (Bundle.main.bundlePath as NSString).pathComponents
let mainPath = NSString.path(withComponents: Array(pathComponents[0...(pathComponents.count - 5)]))
NSWorkspace.shared.launchApplication(mainPath)
NSApp.terminate(nil)
}
}
private let app = NSApplication.shared
private let delegate = AppDelegate()
app.delegate = delegate
app.run()

View File

@@ -0,0 +1,21 @@
# Before and after
With `LaunchAtLogin`, you only have to do 2 steps instead of 13!
```diff
- 1. Create a new target that will be the helper app that launches your app
- 2. Set `LSBackgroundOnly` to true in the `Info.plist` file
- 3. Set `Skip Install` to `YES` in the build settings for the helper app
- 4. Enable sandboxing for the helper app
- 5. Add a new `Copy Files` build phase to the main app
- 6. Select `Wrapper` as destination
- 7. Enter `Contents/Library/LoginItems` as subpath
- 8. Add the helper build product to the build phase
- 9. Copy-paste some boilerplate code into the helper app
- 10. Remember to replace `bundleid.of.main.app` and `MainExectuableName` with your own values
- 11. Copy-paste some code to register the helper app into your main app
- 12. Make sure the main app and helper app use the same code signing certificate
- 13. Manually verify that you did everything correctly
+ 1. Install this package
+ 2. Add a new "Run Script Phase"
```

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.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.

View File

@@ -0,0 +1,88 @@
# LaunchAtLogin
> Add “Launch at Login” functionality to your macOS app in seconds
It's usually quite a [convoluted and error-prone process](before-after.md) to add this. **No more!**
This package works with both sandboxed and non-sandboxed apps and it's App Store compatible and used in apps like [Plash](https://github.com/sindresorhus/Plash), [Dato](https://sindresorhus.com/dato), [Lungo](https://sindresorhus.com/lungo), and [Battery Indicator](https://sindresorhus.com/battery-indicator).
## Requirements
- macOS 10.12+
- Xcode 11+
- Swift 5+
## Install
#### Carthage
```
github "sindresorhus/LaunchAtLogin"
```
## Usage
Add a new ["Run Script Phase"](http://stackoverflow.com/a/39633955/64949) below "Embed Frameworks" in "Build Phases" with the following:
```sh
"${PROJECT_DIR}/Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh"
```
Use it in your app:
```swift
import LaunchAtLogin
print(LaunchAtLogin.isEnabled)
//=> false
LaunchAtLogin.isEnabled = true
print(LaunchAtLogin.isEnabled)
//=> true
```
No need to store any state to UserDefaults.
*Note that the [Mac App Store guidelines](https://developer.apple.com/app-store/review/guidelines/) requires “launch at login” functionality to be enabled in response to a user action. This is usually solved by making it a preference that is disabled by default. Many apps also let the user activate it in a welcome screen.*
## How does it work?
The framework bundles the helper app needed to launch your app and copies it into your app at build time.
## FAQ
#### My app doesn't show up in “System Preferences Users & Groups Login Items”
[This is the expected behavior](https://stackoverflow.com/a/15104481/64949), unfortunately.
#### My app doesn't launch at login when testing
This is usually caused by having one or more older builds of your app laying around somewhere on the system, and macOS picking one of those instead, which doesn't have the launch helper, and thus fails to start.
Some things you can try:
- Bump the version & build of your app so macOS is more likely to pick it.
- Delete the [`DerivedData` directory](https://mgrebenets.github.io/mobile%20ci/2015/02/01/xcode-derived-data).
- Ensure you don't have any other builds laying around somewhere.
Some helpful Stack Overflow answers:
- https://stackoverflow.com/a/43281810/64949
- https://stackoverflow.com/a/51683190/64949
- https://stackoverflow.com/a/53110832/64949
- https://stackoverflow.com/a/53110852/64949
#### Can you support CocoaPods?
CocoaPods used to be supported, but [it did not work well](https://github.com/sindresorhus/LaunchAtLogin/issues/22) and there was no easy way to fix it, so support was dropped. Even though you mainly use CocoaPods, you can still use Carthage just for this package without any problems.
#### I'm getting a `'SMCopyAllJobDictionaries' was deprecated in OS X 10.10` warning
Apple deprecated that API without providing an alternative. Apple engineers have [stated that it's still the preferred API to use](https://github.com/alexzielenski/StartAtLoginController/issues/12#issuecomment-307525807). I plan to use it as long as it's available. There are workarounds I can implement if Apple ever removes the API, so rest assured, this module will be made to work even then. If you want to see this resolved, submit a [Feedback Assistant](https://feedbackassistant.apple.com) report with [the following text](https://github.com/feedback-assistant/reports/issues/16). There's unfortunately still [no way to suppress warnings in Swift](https://stackoverflow.com/a/32861678/64949).
## Related
- [Defaults](https://github.com/sindresorhus/Defaults) - Swifty and modern UserDefaults
- [Preferences](https://github.com/sindresorhus/Preferences) - Add a preferences window to your macOS app in minutes
- [DockProgress](https://github.com/sindresorhus/DockProgress) - Show progress in your app's Dock icon
- [create-dmg](https://github.com/sindresorhus/create-dmg) - Create a good-looking DMG for your macOS app in seconds
- [More…](https://github.com/search?q=user%3Asindresorhus+language%3Aswift)

View File

@@ -0,0 +1,21 @@
//
// HelperToolProtocol.swift
// AlDente
//
// Created by David Wernhart on 13.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import Foundation
let helperVersion: String = "4" //for some reason the integrated version check does not work, so I use this one
@objc(HelperToolProtocol) protocol HelperToolProtocol {
//protocol HelperToolProtocol {
func getVersion(withReply reply: @escaping (String) -> Void)
//TODO: more functions for other data types, altough this is sufficient for battery max charge level
func setSMCByte(key: String, value: UInt8)
func readSMCByte(key: String, withReply reply: @escaping (UInt8) -> Void)
}

1
README.md Normal file
View File

@@ -0,0 +1 @@
# AlDente

437
SMJobBlessUtil.py Executable file
View File

@@ -0,0 +1,437 @@
#! /usr/bin/python
#
# File: SMJobBlessUtil.py
#
# Contains: Tool for checking and correcting apps that use SMJobBless.
#
# Written by: DTS
#
# Copyright: Copyright (c) 2012 Apple Inc. All Rights Reserved.
#
# Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
# ("Apple") in consideration of your agreement to the following
# terms, and your use, installation, modification or
# redistribution of this Apple software constitutes acceptance of
# these terms. If you do not agree with these terms, please do
# not use, install, modify or redistribute this Apple software.
#
# In consideration of your agreement to abide by the following
# terms, and subject to these terms, Apple grants you a personal,
# non-exclusive license, under Apple's copyrights in this
# original Apple software (the "Apple Software"), to use,
# reproduce, modify and redistribute the Apple Software, with or
# without modifications, in source and/or binary forms; provided
# that if you redistribute the Apple Software in its entirety and
# without modifications, you must retain this notice and the
# following text and disclaimers in all such redistributions of
# the Apple Software. Neither the name, trademarks, service marks
# or logos of Apple Inc. may be used to endorse or promote
# products derived from the Apple Software without specific prior
# written permission from Apple. Except as expressly stated in
# this notice, no other rights or licenses, express or implied,
# are granted by Apple herein, including but not limited to any
# patent rights that may be infringed by your derivative works or
# by other works in which the Apple Software may be incorporated.
#
# The Apple Software is provided by Apple on an "AS IS" basis.
# APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
# WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
# THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
# COMBINATION WITH YOUR PRODUCTS.
#
# IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
# INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
# OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
# OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
# OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
# OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
import sys
import os
import getopt
import subprocess
import plistlib
import operator
class UsageException (Exception):
"""
Raised when the progam detects a usage issue; the top-level code catches this
and prints a usage message.
"""
pass
class CheckException (Exception):
"""
Raised when the "check" subcommand detects a problem; the top-level code catches
this and prints a nice error message.
"""
def __init__(self, message, path=None):
self.message = message
self.path = path
def checkCodeSignature(programPath, programType):
"""Checks the code signature of the referenced program."""
# Use the codesign tool to check the signature. The second "-v" is required to enable
# verbose mode, which causes codesign to do more checking. By default it does the minimum
# amount of checking ("Is the program properly signed?"). If you enabled verbose mode it
# does other sanity checks, which we definitely want. The specific thing I'd like to
# detect is "Does the code satisfy its own designated requirement?" and I need to enable
# verbose mode to get that.
args = [
# "false",
"codesign",
"-v",
"-v",
programPath
]
try:
subprocess.check_call(args, stderr=open("/dev/null"))
except subprocess.CalledProcessError, e:
raise CheckException("%s code signature invalid" % programType, programPath)
def readDesignatedRequirement(programPath, programType):
"""Returns the designated requirement of the program as a string."""
args = [
# "false",
"codesign",
"-d",
"-r",
"-",
programPath
]
try:
req = subprocess.check_output(args, stderr=open("/dev/null"))
except subprocess.CalledProcessError, e:
raise CheckException("%s designated requirement unreadable" % programType, programPath)
reqLines = req.splitlines()
if len(reqLines) != 1 or not req.startswith("designated => "):
raise CheckException("%s designated requirement malformed" % programType, programPath)
return reqLines[0][len("designated => "):]
def readInfoPlistFromPath(infoPath):
"""Reads an "Info.plist" file from the specified path."""
try:
info = plistlib.readPlist(infoPath)
except:
raise CheckException("'Info.plist' not readable", infoPath)
if not isinstance(info, dict):
raise CheckException("'Info.plist' root must be a dictionary", infoPath)
return info
def readPlistFromToolSection(toolPath, segmentName, sectionName):
"""Reads a dictionary property list from the specified section within the specified executable."""
# Run otool -s to get a hex dump of the section.
args = [
# "false",
"otool",
"-s",
segmentName,
sectionName,
toolPath
]
try:
plistDump = subprocess.check_output(args)
except subprocess.CalledProcessError, e:
raise CheckException("tool %s / %s section unreadable" % (segmentName, sectionName), toolPath)
# Convert that hex dump to an property list.
plistLines = plistDump.splitlines()
if len(plistLines) < 3 or plistLines[1] != ("Contents of (%s,%s) section" % (segmentName, sectionName)):
raise CheckException("tool %s / %s section dump malformed (1)" % (segmentName, sectionName), toolPath)
del plistLines[0:2]
try:
bytes = []
for line in plistLines:
# line looks like this:
#
# '0000000100000b80\t3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 '
columns = line.split("\t")
assert len(columns) == 2
for hexStr in columns[1].split():
bytes.append(int(hexStr, 16))
plist = plistlib.readPlistFromString(bytearray(bytes))
except:
raise CheckException("tool %s / %s section dump malformed (2)" % (segmentName, sectionName), toolPath)
# Check the root of the property list.
if not isinstance(plist, dict):
raise CheckException("tool %s / %s property list root must be a dictionary" % (segmentName, sectionName), toolPath)
return plist
def checkStep1(appPath):
"""Checks that the app and the tool are both correctly code signed."""
if not os.path.isdir(appPath):
raise CheckException("app not found", appPath)
# Check the app's code signature.
checkCodeSignature(appPath, "app")
# Check the tool directory.
toolDirPath = os.path.join(appPath, "Contents", "Library", "LaunchServices")
if not os.path.isdir(toolDirPath):
raise CheckException("tool directory not found", toolDirPath)
# Check each tool's code signature.
toolPathList = []
for toolName in os.listdir(toolDirPath):
if toolName != ".DS_Store":
toolPath = os.path.join(toolDirPath, toolName)
if not os.path.isfile(toolPath):
raise CheckException("tool directory contains a directory", toolPath)
checkCodeSignature(toolPath, "tool")
toolPathList.append(toolPath)
# Check that we have at least one tool.
if len(toolPathList) == 0:
raise CheckException("no tools found", toolDirPath)
return toolPathList
def checkStep2(appPath, toolPathList):
"""Checks the SMPrivilegedExecutables entry in the app's "Info.plist"."""
# Create a map from the tool name (not path) to its designated requirement.
toolNameToReqMap = dict()
for toolPath in toolPathList:
req = readDesignatedRequirement(toolPath, "tool")
toolNameToReqMap[os.path.basename(toolPath)] = req
# Read the Info.plist for the app and extract the SMPrivilegedExecutables value.
infoPath = os.path.join(appPath, "Contents", "Info.plist")
info = readInfoPlistFromPath(infoPath)
if not info.has_key("SMPrivilegedExecutables"):
raise CheckException("'SMPrivilegedExecutables' not found", infoPath)
infoToolDict = info["SMPrivilegedExecutables"]
if not isinstance(infoToolDict, dict):
raise CheckException("'SMPrivilegedExecutables' must be a dictionary", infoPath)
# Check that the list of tools matches the list of SMPrivilegedExecutables entries.
if sorted(infoToolDict.keys()) != sorted(toolNameToReqMap.keys()):
raise CheckException("'SMPrivilegedExecutables' and tools in 'Contents/Library/LaunchServices' don't match")
# Check that all the requirements match.
# This is an interesting policy choice. Technically the tool just needs to match
# the requirement listed in SMPrivilegedExecutables, and we can check that by
# putting the requirement into tmp.req and then running
#
# $ codesign -v -R tmp.req /path/to/tool
#
# However, for a Developer ID signed tool we really want to have the SMPrivilegedExecutables
# entry contain the tool's designated requirement because Xcode has built a
# more complex DR that does lots of useful and important checks. So, as a matter
# of policy we require that the value in SMPrivilegedExecutables match the tool's DR.
for toolName in infoToolDict:
if infoToolDict[toolName] != toolNameToReqMap[toolName]:
raise CheckException("tool designated requirement (%s) doesn't match entry in 'SMPrivilegedExecutables' (%s)" % (toolNameToReqMap[toolName], infoToolDict[toolName]))
def checkStep3(appPath, toolPathList):
"""Checks the "Info.plist" embedded in each helper tool."""
# First get the app's designated requirement.
appReq = readDesignatedRequirement(appPath, "app")
# Then check that the tool's SMAuthorizedClients value matches it.
for toolPath in toolPathList:
info = readPlistFromToolSection(toolPath, "__TEXT", "__info_plist")
if not info.has_key("CFBundleInfoDictionaryVersion") or info["CFBundleInfoDictionaryVersion"] != "6.0":
raise CheckException("'CFBundleInfoDictionaryVersion' in tool __TEXT / __info_plist section must be '6.0'", toolPath)
if not info.has_key("CFBundleIdentifier") or info["CFBundleIdentifier"] != os.path.basename(toolPath):
raise CheckException("'CFBundleIdentifier' in tool __TEXT / __info_plist section must match tool name", toolPath)
if not info.has_key("SMAuthorizedClients"):
raise CheckException("'SMAuthorizedClients' in tool __TEXT / __info_plist section not found", toolPath)
infoClientList = info["SMAuthorizedClients"]
if not isinstance(infoClientList, list):
raise CheckException("'SMAuthorizedClients' in tool __TEXT / __info_plist section must be an array", toolPath)
if len(infoClientList) != 1:
raise CheckException("'SMAuthorizedClients' in tool __TEXT / __info_plist section must have one entry", toolPath)
# Again, as a matter of policy we require that the SMAuthorizedClients entry must
# match exactly the designated requirement of the app.
if infoClientList[0] != appReq:
raise CheckException("app designated requirement (%s) doesn't match entry in 'SMAuthorizedClients' (%s)" % (appReq, infoClientList[0]), toolPath)
def checkStep4(appPath, toolPathList):
"""Checks the "launchd.plist" embedded in each helper tool."""
for toolPath in toolPathList:
launchd = readPlistFromToolSection(toolPath, "__TEXT", "__launchd_plist")
if not launchd.has_key("Label") or launchd["Label"] != os.path.basename(toolPath):
raise CheckException("'Label' in tool __TEXT / __launchd_plist section must match tool name", toolPath)
# We don't need to check that the label matches the bundle identifier because
# we know it matches the tool name and step 4 checks that the tool name matches
# the bundle identifier.
def checkStep5(appPath):
"""There's nothing to do here; we effectively checked for this is steps 1 and 2."""
pass
def check(appPath):
"""Checks the SMJobBless setup of the specified app."""
# Each of the following steps matches a bullet point in the SMJobBless header doc.
toolPathList = checkStep1(appPath)
checkStep2(appPath, toolPathList)
checkStep3(appPath, toolPathList)
checkStep4(appPath, toolPathList)
checkStep5(appPath)
def setreq(appPath, appInfoPlistPath, toolInfoPlistPaths):
"""
Reads information from the built app and uses it to set the SMJobBless setup
in the specified app and tool Info.plist source files.
"""
if not os.path.isdir(appPath):
raise CheckException("app not found", appPath)
if not os.path.isfile(appInfoPlistPath):
raise CheckException("app 'Info.plist' not found", appInfoPlistPath)
for toolInfoPlistPath in toolInfoPlistPaths:
if not os.path.isfile(toolInfoPlistPath):
raise CheckException("app 'Info.plist' not found", toolInfoPlistPath)
# Get the designated requirement for the app and each of the tools.
appReq = readDesignatedRequirement(appPath, "app")
toolDirPath = os.path.join(appPath, "Contents", "Library", "LaunchServices")
if not os.path.isdir(toolDirPath):
raise CheckException("tool directory not found", toolDirPath)
toolNameToReqMap = {}
for toolName in os.listdir(toolDirPath):
req = readDesignatedRequirement(os.path.join(toolDirPath, toolName), "tool")
toolNameToReqMap[toolName] = req
if len(toolNameToReqMap) > len(toolInfoPlistPaths):
raise CheckException("tool directory has more tools (%d) than you've supplied tool 'Info.plist' paths (%d)" % (len(toolNameToReqMap), len(toolInfoPlistPaths)), toolDirPath)
if len(toolNameToReqMap) < len(toolInfoPlistPaths):
raise CheckException("tool directory has fewer tools (%d) than you've supplied tool 'Info.plist' paths (%d)" % (len(toolNameToReqMap), len(toolInfoPlistPaths)), toolDirPath)
# Build the new value for SMPrivilegedExecutables.
appToolDict = {}
toolInfoPlistPathToToolInfoMap = {}
for toolInfoPlistPath in toolInfoPlistPaths:
toolInfo = readInfoPlistFromPath(toolInfoPlistPath)
toolInfoPlistPathToToolInfoMap[toolInfoPlistPath] = toolInfo
if not toolInfo.has_key("CFBundleIdentifier"):
raise CheckException("'CFBundleIdentifier' not found", toolInfoPlistPath)
bundleID = toolInfo["CFBundleIdentifier"]
if not isinstance(bundleID, basestring):
raise CheckException("'CFBundleIdentifier' must be a string", toolInfoPlistPath)
appToolDict[bundleID] = toolNameToReqMap[bundleID]
# Set the SMPrivilegedExecutables value in the app "Info.plist".
appInfo = readInfoPlistFromPath(appInfoPlistPath)
needsUpdate = not appInfo.has_key("SMPrivilegedExecutables")
if not needsUpdate:
oldAppToolDict = appInfo["SMPrivilegedExecutables"]
if not isinstance(oldAppToolDict, dict):
raise CheckException("'SMPrivilegedExecutables' must be a dictionary", appInfoPlistPath)
appToolDictSorted = sorted(appToolDict.iteritems(), key=operator.itemgetter(0))
oldAppToolDictSorted = sorted(oldAppToolDict.iteritems(), key=operator.itemgetter(0))
needsUpdate = (appToolDictSorted != oldAppToolDictSorted)
if needsUpdate:
appInfo["SMPrivilegedExecutables"] = appToolDict
plistlib.writePlist(appInfo, appInfoPlistPath)
print >> sys.stdout, "%s: updated" % appInfoPlistPath
# Set the SMAuthorizedClients value in each tool's "Info.plist".
toolAppListSorted = [ appReq ] # only one element, so obviously sorted (-:
for toolInfoPlistPath in toolInfoPlistPaths:
toolInfo = toolInfoPlistPathToToolInfoMap[toolInfoPlistPath]
needsUpdate = not toolInfo.has_key("SMAuthorizedClients")
if not needsUpdate:
oldToolAppList = toolInfo["SMAuthorizedClients"]
if not isinstance(oldToolAppList, list):
raise CheckException("'SMAuthorizedClients' must be an array", toolInfoPlistPath)
oldToolAppListSorted = sorted(oldToolAppList)
needsUpdate = (toolAppListSorted != oldToolAppListSorted)
if needsUpdate:
toolInfo["SMAuthorizedClients"] = toolAppListSorted
plistlib.writePlist(toolInfo, toolInfoPlistPath)
print >> sys.stdout, "%s: updated" % toolInfoPlistPath
def main():
options, appArgs = getopt.getopt(sys.argv[1:], "d")
debug = False
for opt, val in options:
if opt == "-d":
debug = True
else:
raise UsageException()
if len(appArgs) == 0:
raise UsageException()
command = appArgs[0]
if command == "check":
if len(appArgs) != 2:
raise UsageException()
check(appArgs[1])
elif command == "setreq":
if len(appArgs) < 4:
raise UsageException()
setreq(appArgs[1], appArgs[2], appArgs[3:])
else:
raise UsageException()
if __name__ == "__main__":
try:
main()
except CheckException, e:
if e.path is None:
print >> sys.stderr, "%s: %s" % (os.path.basename(sys.argv[0]), e.message)
else:
path = e.path
if path.endswith("/"):
path = path[:-1]
print >> sys.stderr, "%s: %s" % (path, e.message)
sys.exit(1)
except UsageException, e:
print >> sys.stderr, "usage: %s check /path/to/app" % os.path.basename(sys.argv[0])
print >> sys.stderr, " %s setreq /path/to/app /path/to/app/Info.plist /path/to/tool/Info.plist..." % os.path.basename(sys.argv[0])
sys.exit(1)

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.davidwernhart.Helper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>com.davidwernhart.Helper</string>
<key>CFBundleVersion</key>
<string>4</string>
<key>SMAuthorizedClients</key>
<array>
<string>identifier &quot;com.davidwernhart.AlDente&quot; and anchor apple generic and certificate leaf[subject.CN] = &quot;Apple Development: david.wernhart96@gmail.com (GSDX9BQ584)&quot; and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.davidwernhart.Helper</string>
<key>MachServices</key>
<dict>
<key>com.davidwernhart.Helper.mach</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,57 @@
//
// HelperTool.swift
// com.davidwernhart.Helper
//
// Created by David Wernhart on 13.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import Foundation
class HelperTool: NSObject, HelperToolProtocol {
func getVersion(withReply reply: (String) -> Void) {
// let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString" as String) as? String ?? "(unknown version)"
// let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String ?? "(unknown build)"
// reply("v\(version) (\(build))")
reply(helperVersion)
}
func setSMCByte(key: String, value: UInt8){
do {
try SMCKit.open()
} catch {
print(error)
exit(EX_UNAVAILABLE)
}
var key = SMCKit.getKey(key, type: DataTypes.UInt8)
let bytes: SMCBytes = (value, UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0))
do {
let status = try SMCKit.writeData(key,data: bytes)
} catch {
}
}
func readSMCByte(key: String, withReply reply: @escaping (UInt8) -> Void){
do {
try SMCKit.open()
} catch {
print(error)
exit(EX_UNAVAILABLE)
}
var key = SMCKit.getKey(key, type: DataTypes.UInt8)
do {
let status = try SMCKit.readData(key).0
reply(status)
} catch {
reply(0)
}
}
}

View File

@@ -0,0 +1,792 @@
//
// SMC.swift
// SMCKit
//
// The MIT License
//
// Copyright (C) 2014-2017 beltex <https://beltex.github.io>
//
// 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 Foundation
//------------------------------------------------------------------------------
// MARK: Type Aliases
//------------------------------------------------------------------------------
// http://stackoverflow.com/a/22383661
/// Floating point, unsigned, 14 bits exponent, 2 bits fraction
public typealias FPE2 = (UInt8, UInt8)
/// Floating point, signed, 7 bits exponent, 8 bits fraction
public typealias SP78 = (UInt8, UInt8)
public typealias SMCBytes = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
UInt8, UInt8, UInt8, UInt8)
//------------------------------------------------------------------------------
// MARK: Standard Library Extensions
//------------------------------------------------------------------------------
extension UInt32 {
init(fromBytes bytes: (UInt8, UInt8, UInt8, UInt8)) {
// TODO: Broken up due to "Expression was too complex" error as of
// Swift 4.
let byte0 = UInt32(bytes.0) << 24
let byte1 = UInt32(bytes.1) << 16
let byte2 = UInt32(bytes.2) << 8
let byte3 = UInt32(bytes.3)
self = byte0 | byte1 | byte2 | byte3
}
}
extension Bool {
init(fromByte byte: UInt8) {
self = byte == 1 ? true : false
}
}
public extension Int {
init(fromFPE2 bytes: FPE2) {
self = (Int(bytes.0) << 6) + (Int(bytes.1) >> 2)
}
func toFPE2() -> FPE2 {
return (UInt8(self >> 6), UInt8((self << 2) ^ ((self >> 6) << 8)))
}
}
extension Double {
init(fromSP78 bytes: SP78) {
// FIXME: Handle second byte
let sign = bytes.0 & 0x80 == 0 ? 1.0 : -1.0
self = sign * Double(bytes.0 & 0x7F) // AND to mask sign bit
}
}
// Thanks to Airspeed Velocity for the great idea!
// http://airspeedvelocity.net/2015/05/22/my-talk-at-swift-summit/
public extension FourCharCode {
init(fromString str: String) {
precondition(str.count == 4)
self = str.utf8.reduce(0) { sum, character in
return sum << 8 | UInt32(character)
}
}
init(fromStaticString str: StaticString) {
precondition(str.utf8CodeUnitCount == 4)
self = str.withUTF8Buffer { buffer in
// TODO: Broken up due to "Expression was too complex" error as of
// Swift 4.
let byte0 = UInt32(buffer[0]) << 24
let byte1 = UInt32(buffer[1]) << 16
let byte2 = UInt32(buffer[2]) << 8
let byte3 = UInt32(buffer[3])
return byte0 | byte1 | byte2 | byte3
}
}
func toString() -> String {
return String(describing: UnicodeScalar(self >> 24 & 0xff)!) +
String(describing: UnicodeScalar(self >> 16 & 0xff)!) +
String(describing: UnicodeScalar(self >> 8 & 0xff)!) +
String(describing: UnicodeScalar(self & 0xff)!)
}
}
//------------------------------------------------------------------------------
// MARK: Defined by AppleSMC.kext
//------------------------------------------------------------------------------
/// Defined by AppleSMC.kext
///
/// This is the predefined struct that must be passed to communicate with the
/// AppleSMC driver. While the driver is closed source, the definition of this
/// struct happened to appear in the Apple PowerManagement project at around
/// version 211, and soon after disappeared. It can be seen in the PrivateLib.c
/// file under pmconfigd. Given that it is C code, this is the closest
/// translation to Swift from a type perspective.
///
/// ### Issues
///
/// * Padding for struct alignment when passed over to C side
/// * Size of struct must be 80 bytes
/// * C array's are bridged as tuples
///
/// http://www.opensource.apple.com/source/PowerManagement/PowerManagement-211/
public struct SMCParamStruct {
/// I/O Kit function selector
public enum Selector: UInt8 {
case kSMCHandleYPCEvent = 2
case kSMCReadKey = 5
case kSMCWriteKey = 6
case kSMCGetKeyFromIndex = 8
case kSMCGetKeyInfo = 9
}
/// Return codes for SMCParamStruct.result property
public enum Result: UInt8 {
case kSMCSuccess = 0
case kSMCError = 1
case kSMCKeyNotFound = 132
}
public struct SMCVersion {
var major: CUnsignedChar = 0
var minor: CUnsignedChar = 0
var build: CUnsignedChar = 0
var reserved: CUnsignedChar = 0
var release: CUnsignedShort = 0
}
public struct SMCPLimitData {
var version: UInt16 = 0
var length: UInt16 = 0
var cpuPLimit: UInt32 = 0
var gpuPLimit: UInt32 = 0
var memPLimit: UInt32 = 0
}
public struct SMCKeyInfoData {
/// How many bytes written to SMCParamStruct.bytes
var dataSize: IOByteCount = 0
/// Type of data written to SMCParamStruct.bytes. This lets us know how
/// to interpret it (translate it to human readable)
var dataType: UInt32 = 0
var dataAttributes: UInt8 = 0
}
/// FourCharCode telling the SMC what we want
var key: UInt32 = 0
var vers = SMCVersion()
var pLimitData = SMCPLimitData()
var keyInfo = SMCKeyInfoData()
/// Padding for struct alignment when passed over to C side
var padding: UInt16 = 0
/// Result of an operation
var result: UInt8 = 0
var status: UInt8 = 0
/// Method selector
var data8: UInt8 = 0
var data32: UInt32 = 0
/// Data returned from the SMC
var bytes: SMCBytes = (UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0))
}
//------------------------------------------------------------------------------
// MARK: SMC Client
//------------------------------------------------------------------------------
/// SMC data type information
public struct DataTypes {
/// Fan information struct
public static let FDS =
DataType(type: FourCharCode(fromStaticString: "{fds"), size: 16)
public static let Flag =
DataType(type: FourCharCode(fromStaticString: "flag"), size: 1)
/// See type aliases
public static let FPE2 =
DataType(type: FourCharCode(fromStaticString: "fpe2"), size: 2)
/// See type aliases
public static let SP78 =
DataType(type: FourCharCode(fromStaticString: "sp78"), size: 2)
public static let UInt8 =
DataType(type: FourCharCode(fromStaticString: "ui8 "), size: 1)
public static let UInt32 =
DataType(type: FourCharCode(fromStaticString: "ui32"), size: 4)
}
public struct SMCKey {
let code: FourCharCode
let info: DataType
}
public struct DataType: Equatable {
let type: FourCharCode
let size: UInt32
}
public func ==(lhs: DataType, rhs: DataType) -> Bool {
return lhs.type == rhs.type && lhs.size == rhs.size
}
/// Apple System Management Controller (SMC) user-space client for Intel-based
/// Macs. Works by talking to the AppleSMC.kext (kernel extension), the closed
/// source driver for the SMC.
public struct SMCKit {
public enum SMCError: Error {
/// AppleSMC driver not found
case driverNotFound
/// Failed to open a connection to the AppleSMC driver
case failedToOpen
/// This SMC key is not valid on this machine
case keyNotFound(code: String)
/// Requires root privileges
case notPrivileged
/// Fan speed must be > 0 && <= fanMaxSpeed
case unsafeFanSpeed
/// https://developer.apple.com/library/mac/qa/qa1075/_index.html
///
/// - parameter kIOReturn: I/O Kit error code
/// - parameter SMCResult: SMC specific return code
case unknown(kIOReturn: kern_return_t, SMCResult: UInt8)
}
/// Connection to the SMC driver
fileprivate static var connection: io_connect_t = 0
/// Open connection to the SMC driver. This must be done first before any
/// other calls
public static func open() throws {
let service = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("AppleSMC"))
if service == 0 { throw SMCError.driverNotFound }
let result = IOServiceOpen(service, mach_task_self_, 0,
&SMCKit.connection)
IOObjectRelease(service)
if result != kIOReturnSuccess { throw SMCError.failedToOpen }
}
/// Close connection to the SMC driver
@discardableResult
public static func close() -> Bool {
let result = IOServiceClose(SMCKit.connection)
return result == kIOReturnSuccess ? true : false
}
/// Get information about a key
public static func keyInformation(_ key: FourCharCode) throws -> DataType {
var inputStruct = SMCParamStruct()
inputStruct.key = key
inputStruct.data8 = SMCParamStruct.Selector.kSMCGetKeyInfo.rawValue
let outputStruct = try callDriver(&inputStruct)
return DataType(type: outputStruct.keyInfo.dataType,
size: outputStruct.keyInfo.dataSize)
}
/// Get information about the key at index
public static func keyInformationAtIndex(_ index: Int) throws ->
FourCharCode {
var inputStruct = SMCParamStruct()
inputStruct.data8 = SMCParamStruct.Selector.kSMCGetKeyFromIndex.rawValue
inputStruct.data32 = UInt32(index)
let outputStruct = try callDriver(&inputStruct)
return outputStruct.key
}
public static func getKey(_ code:String,type:DataType) -> SMCKey{
let key = SMCKey(code: FourCharCode(fromString: code),info: type)
return key
}
/// Read data of a key
public static func readData(_ key: SMCKey) throws -> SMCBytes {
var inputStruct = SMCParamStruct()
inputStruct.key = key.code
inputStruct.keyInfo.dataSize = UInt32(key.info.size)
inputStruct.data8 = SMCParamStruct.Selector.kSMCReadKey.rawValue
let outputStruct = try callDriver(&inputStruct)
return outputStruct.bytes
}
/// Write data for a key
public static func writeData(_ key: SMCKey, data: SMCBytes) throws {
var inputStruct = SMCParamStruct()
inputStruct.key = key.code
inputStruct.bytes = data
inputStruct.keyInfo.dataSize = UInt32(key.info.size)
inputStruct.data8 = SMCParamStruct.Selector.kSMCWriteKey.rawValue
_ = try callDriver(&inputStruct)
}
/// Make an actual call to the SMC driver
public static func callDriver(_ inputStruct: inout SMCParamStruct,
selector: SMCParamStruct.Selector = .kSMCHandleYPCEvent)
throws -> SMCParamStruct {
assert(MemoryLayout<SMCParamStruct>.stride == 80, "SMCParamStruct size is != 80")
var outputStruct = SMCParamStruct()
let inputStructSize = MemoryLayout<SMCParamStruct>.stride
var outputStructSize = MemoryLayout<SMCParamStruct>.stride
let result = IOConnectCallStructMethod(SMCKit.connection,
UInt32(selector.rawValue),
&inputStruct,
inputStructSize,
&outputStruct,
&outputStructSize)
switch (result, outputStruct.result) {
case (kIOReturnSuccess, SMCParamStruct.Result.kSMCSuccess.rawValue):
return outputStruct
case (kIOReturnSuccess, SMCParamStruct.Result.kSMCKeyNotFound.rawValue):
throw SMCError.keyNotFound(code: inputStruct.key.toString())
case (kIOReturnNotPrivileged, _):
throw SMCError.notPrivileged
default:
throw SMCError.unknown(kIOReturn: result,
SMCResult: outputStruct.result)
}
}
}
//------------------------------------------------------------------------------
// MARK: General
//------------------------------------------------------------------------------
extension SMCKit {
/// Get all valid SMC keys for this machine
public static func allKeys() throws -> [SMCKey] {
let count = try keyCount()
var keys = [SMCKey]()
for i in 0 ..< count {
let key = try keyInformationAtIndex(i)
let info = try keyInformation(key)
keys.append(SMCKey(code: key, info: info))
}
return keys
}
/// Get the number of valid SMC keys for this machine
public static func keyCount() throws -> Int {
let key = SMCKey(code: FourCharCode(fromStaticString: "#KEY"),
info: DataTypes.UInt32)
let data = try readData(key)
return Int(UInt32(fromBytes: (data.0, data.1, data.2, data.3)))
}
/// Is this key valid on this machine?
public static func isKeyFound(_ code: FourCharCode) throws -> Bool {
do {
_ = try keyInformation(code)
} catch SMCError.keyNotFound { return false }
return true
}
}
//------------------------------------------------------------------------------
// MARK: Temperature
//------------------------------------------------------------------------------
/// The list is NOT exhaustive. In addition, the names of the sensors may not be
/// mapped to the correct hardware component.
///
/// ### Sources
///
/// * powermetrics(1)
/// * https://www.apple.com/downloads/dashboard/status/istatpro.html
/// * https://github.com/hholtmann/smcFanControl
/// * https://github.com/jedda/OSX-Monitoring-Tools
/// * http://www.opensource.apple.com/source/net_snmp/
/// * http://www.parhelia.ch/blog/statics/k3_keys.html
public struct TemperatureSensors {
public static let AMBIENT_AIR_0 = TemperatureSensor(name: "AMBIENT_AIR_0",
code: FourCharCode(fromStaticString: "TA0P"))
public static let AMBIENT_AIR_1 = TemperatureSensor(name: "AMBIENT_AIR_1",
code: FourCharCode(fromStaticString: "TA1P"))
// Via powermetrics(1)
public static let CPU_0_DIE = TemperatureSensor(name: "CPU_0_DIE",
code: FourCharCode(fromStaticString: "TC0F"))
public static let CPU_0_DIODE = TemperatureSensor(name: "CPU_0_DIODE",
code: FourCharCode(fromStaticString: "TC0D"))
public static let CPU_0_HEATSINK = TemperatureSensor(name: "CPU_0_HEATSINK",
code: FourCharCode(fromStaticString: "TC0H"))
public static let CPU_0_PROXIMITY =
TemperatureSensor(name: "CPU_0_PROXIMITY",
code: FourCharCode(fromStaticString: "TC0P"))
public static let ENCLOSURE_BASE_0 =
TemperatureSensor(name: "ENCLOSURE_BASE_0",
code: FourCharCode(fromStaticString: "TB0T"))
public static let ENCLOSURE_BASE_1 =
TemperatureSensor(name: "ENCLOSURE_BASE_1",
code: FourCharCode(fromStaticString: "TB1T"))
public static let ENCLOSURE_BASE_2 =
TemperatureSensor(name: "ENCLOSURE_BASE_2",
code: FourCharCode(fromStaticString: "TB2T"))
public static let ENCLOSURE_BASE_3 =
TemperatureSensor(name: "ENCLOSURE_BASE_3",
code: FourCharCode(fromStaticString: "TB3T"))
public static let GPU_0_DIODE = TemperatureSensor(name: "GPU_0_DIODE",
code: FourCharCode(fromStaticString: "TG0D"))
public static let GPU_0_HEATSINK = TemperatureSensor(name: "GPU_0_HEATSINK",
code: FourCharCode(fromStaticString: "TG0H"))
public static let GPU_0_PROXIMITY =
TemperatureSensor(name: "GPU_0_PROXIMITY",
code: FourCharCode(fromStaticString: "TG0P"))
public static let HDD_PROXIMITY = TemperatureSensor(name: "HDD_PROXIMITY",
code: FourCharCode(fromStaticString: "TH0P"))
public static let HEATSINK_0 = TemperatureSensor(name: "HEATSINK_0",
code: FourCharCode(fromStaticString: "Th0H"))
public static let HEATSINK_1 = TemperatureSensor(name: "HEATSINK_1",
code: FourCharCode(fromStaticString: "Th1H"))
public static let HEATSINK_2 = TemperatureSensor(name: "HEATSINK_2",
code: FourCharCode(fromStaticString: "Th2H"))
public static let LCD_PROXIMITY = TemperatureSensor(name: "LCD_PROXIMITY",
code: FourCharCode(fromStaticString: "TL0P"))
public static let MEM_SLOT_0 = TemperatureSensor(name: "MEM_SLOT_0",
code: FourCharCode(fromStaticString: "TM0S"))
public static let MEM_SLOTS_PROXIMITY =
TemperatureSensor(name: "MEM_SLOTS_PROXIMITY",
code: FourCharCode(fromStaticString: "TM0P"))
public static let MISC_PROXIMITY = TemperatureSensor(name: "MISC_PROXIMITY",
code: FourCharCode(fromStaticString: "Tm0P"))
public static let NORTHBRIDGE = TemperatureSensor(name: "NORTHBRIDGE",
code: FourCharCode(fromStaticString: "TN0H"))
public static let NORTHBRIDGE_DIODE =
TemperatureSensor(name: "NORTHBRIDGE_DIODE",
code: FourCharCode(fromStaticString: "TN0D"))
public static let NORTHBRIDGE_PROXIMITY =
TemperatureSensor(name: "NORTHBRIDGE_PROXIMITY",
code: FourCharCode(fromStaticString: "TN0P"))
public static let ODD_PROXIMITY = TemperatureSensor(name: "ODD_PROXIMITY",
code: FourCharCode(fromStaticString: "TO0P"))
public static let PALM_REST = TemperatureSensor(name: "PALM_REST",
code: FourCharCode(fromStaticString: "Ts0P"))
public static let PWR_SUPPLY_PROXIMITY =
TemperatureSensor(name: "PWR_SUPPLY_PROXIMITY",
code: FourCharCode(fromStaticString: "Tp0P"))
public static let THUNDERBOLT_0 = TemperatureSensor(name: "THUNDERBOLT_0",
code: FourCharCode(fromStaticString: "TI0P"))
public static let THUNDERBOLT_1 = TemperatureSensor(name: "THUNDERBOLT_1",
code: FourCharCode(fromStaticString: "TI1P"))
public static let all = [AMBIENT_AIR_0.code : AMBIENT_AIR_0,
AMBIENT_AIR_1.code : AMBIENT_AIR_1,
CPU_0_DIE.code : CPU_0_DIE,
CPU_0_DIODE.code : CPU_0_DIODE,
CPU_0_HEATSINK.code : CPU_0_HEATSINK,
CPU_0_PROXIMITY.code : CPU_0_PROXIMITY,
ENCLOSURE_BASE_0.code : ENCLOSURE_BASE_0,
ENCLOSURE_BASE_1.code : ENCLOSURE_BASE_1,
ENCLOSURE_BASE_2.code : ENCLOSURE_BASE_2,
ENCLOSURE_BASE_3.code : ENCLOSURE_BASE_3,
GPU_0_DIODE.code : GPU_0_DIODE,
GPU_0_HEATSINK.code : GPU_0_HEATSINK,
GPU_0_PROXIMITY.code : GPU_0_PROXIMITY,
HDD_PROXIMITY.code : HDD_PROXIMITY,
HEATSINK_0.code : HEATSINK_0,
HEATSINK_1.code : HEATSINK_1,
HEATSINK_2.code : HEATSINK_2,
MEM_SLOT_0.code : MEM_SLOT_0,
MEM_SLOTS_PROXIMITY.code: MEM_SLOTS_PROXIMITY,
PALM_REST.code : PALM_REST,
LCD_PROXIMITY.code : LCD_PROXIMITY,
MISC_PROXIMITY.code : MISC_PROXIMITY,
NORTHBRIDGE.code : NORTHBRIDGE,
NORTHBRIDGE_DIODE.code : NORTHBRIDGE_DIODE,
NORTHBRIDGE_PROXIMITY.code : NORTHBRIDGE_PROXIMITY,
ODD_PROXIMITY.code : ODD_PROXIMITY,
PWR_SUPPLY_PROXIMITY.code : PWR_SUPPLY_PROXIMITY,
THUNDERBOLT_0.code : THUNDERBOLT_0,
THUNDERBOLT_1.code : THUNDERBOLT_1]
}
public struct TemperatureSensor {
public let name: String
public let code: FourCharCode
}
public enum TemperatureUnit {
case celius
case fahrenheit
case kelvin
public static func toFahrenheit(_ celius: Double) -> Double {
// https://en.wikipedia.org/wiki/Fahrenheit#Definition_and_conversions
return (celius * 1.8) + 32
}
public static func toKelvin(_ celius: Double) -> Double {
// https://en.wikipedia.org/wiki/Kelvin
return celius + 273.15
}
}
extension SMCKit {
public static func allKnownTemperatureSensors() throws ->
[TemperatureSensor] {
var sensors = [TemperatureSensor]()
for sensor in TemperatureSensors.all.values {
if try isKeyFound(sensor.code) { sensors.append(sensor) }
}
return sensors
}
public static func allUnknownTemperatureSensors() throws -> [TemperatureSensor] {
let keys = try allKeys()
return keys.filter { $0.code.toString().hasPrefix("T") &&
$0.info == DataTypes.SP78 &&
TemperatureSensors.all[$0.code] == nil }
.map { TemperatureSensor(name: "Unknown", code: $0.code) }
}
/// Get current temperature of a sensor
public static func temperature(_ sensorCode: FourCharCode,
unit: TemperatureUnit = .celius) throws -> Double {
let data = try readData(SMCKey(code: sensorCode, info: DataTypes.SP78))
let temperatureInCelius = Double(fromSP78: (data.0, data.1))
switch unit {
case .celius:
return temperatureInCelius
case .fahrenheit:
return TemperatureUnit.toFahrenheit(temperatureInCelius)
case .kelvin:
return TemperatureUnit.toKelvin(temperatureInCelius)
}
}
}
//------------------------------------------------------------------------------
// MARK: Fan
//------------------------------------------------------------------------------
public struct Fan {
// TODO: Should we start the fan id from 1 instead of 0?
public let id: Int
public let name: String
public let minSpeed: Int
public let maxSpeed: Int
}
extension SMCKit {
public static func allFans() throws -> [Fan] {
let count = try fanCount()
var fans = [Fan]()
for i in 0 ..< count {
fans.append(try SMCKit.fan(i))
}
return fans
}
public static func fan(_ id: Int) throws -> Fan {
let name = try fanName(id)
let minSpeed = try fanMinSpeed(id)
let maxSpeed = try fanMaxSpeed(id)
return Fan(id: id, name: name, minSpeed: minSpeed, maxSpeed: maxSpeed)
}
/// Number of fans this machine has. All Intel based Macs, except for the
/// 2015 MacBook (8,1), have at least 1
public static func fanCount() throws -> Int {
let key = SMCKey(code: FourCharCode(fromStaticString: "FNum"),
info: DataTypes.UInt8)
let data = try readData(key)
return Int(data.0)
}
public static func fanName(_ id: Int) throws -> String {
let key = SMCKey(code: FourCharCode(fromString: "F\(id)ID"),
info: DataTypes.FDS)
let data = try readData(key)
// The last 12 bytes of '{fds' data type, a custom struct defined by the
// AppleSMC.kext that is 16 bytes, contains the fan name
let c1 = String(UnicodeScalar(data.4))
let c2 = String(UnicodeScalar(data.5))
let c3 = String(UnicodeScalar(data.6))
let c4 = String(UnicodeScalar(data.7))
let c5 = String(UnicodeScalar(data.8))
let c6 = String(UnicodeScalar(data.9))
let c7 = String(UnicodeScalar(data.10))
let c8 = String(UnicodeScalar(data.11))
let c9 = String(UnicodeScalar(data.12))
let c10 = String(UnicodeScalar(data.13))
let c11 = String(UnicodeScalar(data.14))
let c12 = String(UnicodeScalar(data.15))
let name = c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9 + c10 + c11 + c12
let characterSet = CharacterSet.whitespaces
return name.trimmingCharacters(in: characterSet)
}
public static func fanCurrentSpeed(_ id: Int) throws -> Int {
let key = SMCKey(code: FourCharCode(fromString: "F\(id)Ac"),
info: DataTypes.FPE2)
let data = try readData(key)
return Int(fromFPE2: (data.0, data.1))
}
public static func fanMinSpeed(_ id: Int) throws -> Int {
let key = SMCKey(code: FourCharCode(fromString: "F\(id)Mn"),
info: DataTypes.FPE2)
let data = try readData(key)
return Int(fromFPE2: (data.0, data.1))
}
public static func fanMaxSpeed(_ id: Int) throws -> Int {
let key = SMCKey(code: FourCharCode(fromString: "F\(id)Mx"),
info: DataTypes.FPE2)
let data = try readData(key)
return Int(fromFPE2: (data.0, data.1))
}
/// Requires root privileges. By minimum we mean that OS X can interject and
/// raise the fan speed if needed, however it will not go below this.
///
/// WARNING: You are playing with hardware here, BE CAREFUL.
///
/// - Throws: Of note, `SMCKit.SMCError`'s `UnsafeFanSpeed` and `NotPrivileged`
public static func fanSetMinSpeed(_ id: Int, speed: Int) throws {
let maxSpeed = try fanMaxSpeed(id)
if speed <= 0 || speed > maxSpeed { throw SMCError.unsafeFanSpeed }
let data = speed.toFPE2()
let bytes: SMCBytes = (data.0, data.1, UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
UInt8(0), UInt8(0))
let key = SMCKey(code: FourCharCode(fromString: "F\(id)Mn"),
info: DataTypes.FPE2)
try writeData(key, data: bytes)
}
}
//------------------------------------------------------------------------------
// MARK: Miscellaneous
//------------------------------------------------------------------------------
public struct batteryInfo {
public let batteryCount: Int
public let isACPresent: Bool
public let isBatteryPowered: Bool
public let isBatteryOk: Bool
public let isCharging: Bool
}
extension SMCKit {
public static func isOpticalDiskDriveFull() throws -> Bool {
// TODO: Should we catch key not found? That just means the machine
// doesn't have an ODD. Returning false though is not fully correct.
// Maybe we could throw a no ODD error instead?
let key = SMCKey(code: FourCharCode(fromStaticString: "MSDI"),
info: DataTypes.Flag)
let data = try readData(key)
return Bool(fromByte: data.0)
}
public static func batteryInformation() throws -> batteryInfo {
let batteryCountKey =
SMCKey(code: FourCharCode(fromStaticString: "BNum"),
info: DataTypes.UInt8)
let batteryPoweredKey =
SMCKey(code: FourCharCode(fromStaticString: "BATP"),
info: DataTypes.Flag)
let batteryInfoKey =
SMCKey(code: FourCharCode(fromStaticString: "BSIn"),
info: DataTypes.UInt8)
let batteryCountData = try readData(batteryCountKey)
let batteryCount = Int(batteryCountData.0)
let isBatteryPoweredData = try readData(batteryPoweredKey)
let isBatteryPowered = Bool(fromByte: isBatteryPoweredData.0)
let batteryInfoData = try readData(batteryInfoKey)
let isCharging = batteryInfoData.0 & 1 == 1 ? true : false
let isACPresent = (batteryInfoData.0 >> 1) & 1 == 1 ? true : false
let isBatteryOk = (batteryInfoData.0 >> 6) & 1 == 1 ? true : false
return batteryInfo(batteryCount: batteryCount, isACPresent: isACPresent,
isBatteryPowered: isBatteryPowered,
isBatteryOk: isBatteryOk,
isCharging: isCharging)
}
}

View File

@@ -0,0 +1,25 @@
//
// main.swift
// com.davidwernhart.Helper
//
// Created by David Wernhart on 10.02.20.
// Copyright © 2020 David Wernhart. All rights reserved.
//
import Foundation
class HelperDelegate: NSObject, NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
newConnection.exportedInterface = NSXPCInterface(with: HelperToolProtocol.self)
newConnection.exportedObject = HelperTool()
newConnection.resume()
return true
}
}
let delegate = HelperDelegate()
let listener = NSXPCListener(machServiceName: "com.davidwernhart.Helper.mach")
listener.delegate = delegate
listener.resume()
RunLoop.current.run()