├── .gitignore ├── ALCPlugFix.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── goodwin.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── goodwin.xcuserdatad │ └── xcschemes │ ├── ALCPlugFix.xcscheme │ └── xcschememanagement.plist ├── ALCPlugFix ├── 1.plist └── main.m ├── Info.plist ├── README.MD ├── good.win.ALCPlugFix.plist ├── hda-verb ├── install.sh └── uninstall.sh /.gitignore: -------------------------------------------------------------------------------- 1 | ## Build generated 2 | build/ 3 | DerivedData 4 | 5 | ## Various settings 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | 16 | ## Other 17 | *.xccheckout 18 | *.moved-aside 19 | *.xcuserstate 20 | *.xcscmblueprint 21 | *.xcscheme 22 | 23 | ## OS Generated 24 | .DS_Store 25 | .DS_Store? 26 | -------------------------------------------------------------------------------- /ALCPlugFix.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4C761DB422710250004042C9 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C761DB322710250004042C9 /* AppKit.framework */; }; 11 | 4CE328391DCA9A59002A53ED /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE328381DCA9A59002A53ED /* main.m */; }; 12 | D96DD8E9562DA5C656BFF568 /* README.MD in Sources */ = {isa = PBXBuildFile; fileRef = D96BFF009CB392050D064A88 /* README.MD */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 4CE328331DCA9A59002A53ED /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = /usr/share/man/man1/; 20 | dstSubfolderSpec = 0; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 1; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 4C761DB322710250004042C9 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 29 | 4CE328351DCA9A59002A53ED /* ALCPlugFix */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ALCPlugFix; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 4CE328381DCA9A59002A53ED /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | D96BFF009CB392050D064A88 /* README.MD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.MD; sourceTree = ""; }; 32 | DF72946424AA7A4B005B9AA5 /* good.win.ALCPlugFix.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = good.win.ALCPlugFix.plist; sourceTree = ""; }; 33 | DF72946524AA7A50005B9AA5 /* hda-verb */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = "hda-verb"; sourceTree = ""; }; 34 | DF72946624AA7A53005B9AA5 /* install.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install.sh; sourceTree = ""; }; 35 | DF72946724AA7A56005B9AA5 /* uninstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = uninstall.sh; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 4CE328321DCA9A59002A53ED /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | 4C761DB422710250004042C9 /* AppKit.framework in Frameworks */, 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 4C761DB222710250004042C9 /* Frameworks */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 4C761DB322710250004042C9 /* AppKit.framework */, 54 | ); 55 | name = Frameworks; 56 | sourceTree = ""; 57 | }; 58 | 4CE3282C1DCA9A59002A53ED = { 59 | isa = PBXGroup; 60 | children = ( 61 | 4CE328371DCA9A59002A53ED /* ALCPlugFix */, 62 | 4CE328361DCA9A59002A53ED /* Products */, 63 | 4C761DB222710250004042C9 /* Frameworks */, 64 | D96BFF009CB392050D064A88 /* README.MD */, 65 | DF72946424AA7A4B005B9AA5 /* good.win.ALCPlugFix.plist */, 66 | DF72946524AA7A50005B9AA5 /* hda-verb */, 67 | DF72946624AA7A53005B9AA5 /* install.sh */, 68 | DF72946724AA7A56005B9AA5 /* uninstall.sh */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 4CE328361DCA9A59002A53ED /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 4CE328351DCA9A59002A53ED /* ALCPlugFix */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 4CE328371DCA9A59002A53ED /* ALCPlugFix */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 4CE328381DCA9A59002A53ED /* main.m */, 84 | ); 85 | path = ALCPlugFix; 86 | sourceTree = ""; 87 | }; 88 | /* End PBXGroup section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 4CE328341DCA9A59002A53ED /* ALCPlugFix */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 4CE3283C1DCA9A59002A53ED /* Build configuration list for PBXNativeTarget "ALCPlugFix" */; 94 | buildPhases = ( 95 | 4CE328311DCA9A59002A53ED /* Sources */, 96 | 4CE328321DCA9A59002A53ED /* Frameworks */, 97 | 4CE328331DCA9A59002A53ED /* CopyFiles */, 98 | ); 99 | buildRules = ( 100 | ); 101 | dependencies = ( 102 | ); 103 | name = ALCPlugFix; 104 | productName = ALCPlugFix; 105 | productReference = 4CE328351DCA9A59002A53ED /* ALCPlugFix */; 106 | productType = "com.apple.product-type.tool"; 107 | }; 108 | /* End PBXNativeTarget section */ 109 | 110 | /* Begin PBXProject section */ 111 | 4CE3282D1DCA9A59002A53ED /* Project object */ = { 112 | isa = PBXProject; 113 | attributes = { 114 | LastUpgradeCheck = 1030; 115 | ORGANIZATIONNAME = "Oleksandr Stoyevskyy"; 116 | TargetAttributes = { 117 | 4CE328341DCA9A59002A53ED = { 118 | CreatedOnToolsVersion = 8.1; 119 | ProvisioningStyle = Automatic; 120 | }; 121 | }; 122 | }; 123 | buildConfigurationList = 4CE328301DCA9A59002A53ED /* Build configuration list for PBXProject "ALCPlugFix" */; 124 | compatibilityVersion = "Xcode 3.2"; 125 | developmentRegion = en; 126 | hasScannedForEncodings = 0; 127 | knownRegions = ( 128 | en, 129 | Base, 130 | ); 131 | mainGroup = 4CE3282C1DCA9A59002A53ED; 132 | productRefGroup = 4CE328361DCA9A59002A53ED /* Products */; 133 | projectDirPath = ""; 134 | projectRoot = ""; 135 | targets = ( 136 | 4CE328341DCA9A59002A53ED /* ALCPlugFix */, 137 | ); 138 | }; 139 | /* End PBXProject section */ 140 | 141 | /* Begin PBXSourcesBuildPhase section */ 142 | 4CE328311DCA9A59002A53ED /* Sources */ = { 143 | isa = PBXSourcesBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | 4CE328391DCA9A59002A53ED /* main.m in Sources */, 147 | D96DD8E9562DA5C656BFF568 /* README.MD in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin XCBuildConfiguration section */ 154 | 4CE3283A1DCA9A59002A53ED /* Debug */ = { 155 | isa = XCBuildConfiguration; 156 | buildSettings = { 157 | ALWAYS_SEARCH_USER_PATHS = NO; 158 | CLANG_ANALYZER_NONNULL = YES; 159 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 160 | CLANG_CXX_LIBRARY = "libc++"; 161 | CLANG_ENABLE_MODULES = YES; 162 | CLANG_ENABLE_OBJC_ARC = YES; 163 | CLANG_WARN_BOOL_CONVERSION = YES; 164 | CLANG_WARN_CONSTANT_CONVERSION = YES; 165 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 166 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 167 | CLANG_WARN_EMPTY_BODY = YES; 168 | CLANG_WARN_ENUM_CONVERSION = YES; 169 | CLANG_WARN_INFINITE_RECURSION = YES; 170 | CLANG_WARN_INT_CONVERSION = YES; 171 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 172 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 173 | CLANG_WARN_UNREACHABLE_CODE = YES; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | CODE_SIGN_IDENTITY = "-"; 176 | COPY_PHASE_STRIP = NO; 177 | DEBUG_INFORMATION_FORMAT = dwarf; 178 | ENABLE_STRICT_OBJC_MSGSEND = YES; 179 | ENABLE_TESTABILITY = YES; 180 | GCC_C_LANGUAGE_STANDARD = gnu99; 181 | GCC_DYNAMIC_NO_PIC = NO; 182 | GCC_NO_COMMON_BLOCKS = YES; 183 | GCC_OPTIMIZATION_LEVEL = 0; 184 | GCC_PREPROCESSOR_DEFINITIONS = ( 185 | "DEBUG=1", 186 | "$(inherited)", 187 | ); 188 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 189 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 190 | GCC_WARN_UNDECLARED_SELECTOR = YES; 191 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 192 | GCC_WARN_UNUSED_FUNCTION = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | MACOSX_DEPLOYMENT_TARGET = 10.11; 195 | MTL_ENABLE_DEBUG_INFO = YES; 196 | ONLY_ACTIVE_ARCH = YES; 197 | SDKROOT = macosx; 198 | }; 199 | name = Debug; 200 | }; 201 | 4CE3283B1DCA9A59002A53ED /* Release */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | CLANG_ANALYZER_NONNULL = YES; 206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 207 | CLANG_CXX_LIBRARY = "libc++"; 208 | CLANG_ENABLE_MODULES = YES; 209 | CLANG_ENABLE_OBJC_ARC = YES; 210 | CLANG_WARN_BOOL_CONVERSION = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 219 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | CODE_SIGN_IDENTITY = "-"; 223 | COPY_PHASE_STRIP = NO; 224 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 225 | ENABLE_NS_ASSERTIONS = NO; 226 | ENABLE_STRICT_OBJC_MSGSEND = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu99; 228 | GCC_NO_COMMON_BLOCKS = YES; 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | MACOSX_DEPLOYMENT_TARGET = 10.11; 236 | MTL_ENABLE_DEBUG_INFO = NO; 237 | SDKROOT = macosx; 238 | }; 239 | name = Release; 240 | }; 241 | 4CE3283D1DCA9A59002A53ED /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | PRODUCT_NAME = "$(TARGET_NAME)"; 245 | }; 246 | name = Debug; 247 | }; 248 | 4CE3283E1DCA9A59002A53ED /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | PRODUCT_NAME = "$(TARGET_NAME)"; 252 | }; 253 | name = Release; 254 | }; 255 | /* End XCBuildConfiguration section */ 256 | 257 | /* Begin XCConfigurationList section */ 258 | 4CE328301DCA9A59002A53ED /* Build configuration list for PBXProject "ALCPlugFix" */ = { 259 | isa = XCConfigurationList; 260 | buildConfigurations = ( 261 | 4CE3283A1DCA9A59002A53ED /* Debug */, 262 | 4CE3283B1DCA9A59002A53ED /* Release */, 263 | ); 264 | defaultConfigurationIsVisible = 0; 265 | defaultConfigurationName = Release; 266 | }; 267 | 4CE3283C1DCA9A59002A53ED /* Build configuration list for PBXNativeTarget "ALCPlugFix" */ = { 268 | isa = XCConfigurationList; 269 | buildConfigurations = ( 270 | 4CE3283D1DCA9A59002A53ED /* Debug */, 271 | 4CE3283E1DCA9A59002A53ED /* Release */, 272 | ); 273 | defaultConfigurationIsVisible = 0; 274 | defaultConfigurationName = Release; 275 | }; 276 | /* End XCConfigurationList section */ 277 | }; 278 | rootObject = 4CE3282D1DCA9A59002A53ED /* Project object */; 279 | } 280 | -------------------------------------------------------------------------------- /ALCPlugFix.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ALCPlugFix.xcodeproj/project.xcworkspace/xcuserdata/goodwin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sniki/ALCPlugFix/b73ff371ed1597d485dd10f11e32ad0d80bbe409/ALCPlugFix.xcodeproj/project.xcworkspace/xcuserdata/goodwin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ALCPlugFix.xcodeproj/xcuserdata/goodwin.xcuserdatad/xcschemes/ALCPlugFix.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ALCPlugFix.xcodeproj/xcuserdata/goodwin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ALCPlugFix.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4CE328341DCA9A59002A53ED 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ALCPlugFix/1.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | KeepAlive 6 | 7 | Label 8 | good.win.ALCPlugFix 9 | ProgramArguments 10 | 11 | /Library/MyDaemon/Daemon/ 12 | 13 | RunAtLoad 14 | 15 | ServiceIPC 16 | 17 | /* 18 | StandardErrorPath 19 | /Library/Logs/MyDaemon.log 20 | StandardOutPath 21 | /Library/Logs/MyDaemon.log 22 | */ 23 | 24 | 25 | -------------------------------------------------------------------------------- /ALCPlugFix/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ALCPlugFix 4 | // 5 | // Created by Oleksandr Stoyevskyy on 11/3/16. 6 | // Copyright © 2016 Oleksandr Stoyevskyy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | 14 | void fixAudio(); 15 | NSString *binPrefix; 16 | 17 | @protocol DaemonProtocol 18 | - (void)performWork; 19 | @end 20 | 21 | @interface NSString (ShellExecution) 22 | - (NSString*)runAsCommand; 23 | @end 24 | 25 | @implementation NSString (ShellExecution) 26 | 27 | - (NSString*)runAsCommand { 28 | NSPipe* pipe = [NSPipe pipe]; 29 | 30 | NSTask* task = [[NSTask alloc] init]; 31 | [task setLaunchPath: @"/bin/sh"]; 32 | [task setArguments:@[@"-c", [NSString stringWithFormat:@"%@", self]]]; 33 | [task setStandardOutput:pipe]; 34 | 35 | NSFileHandle* file = [pipe fileHandleForReading]; 36 | [task launch]; 37 | 38 | return [[NSString alloc] initWithData:[file readDataToEndOfFile] encoding:NSUTF8StringEncoding]; 39 | } 40 | 41 | @end 42 | 43 | # pragma mark ALCPlugFix Object Conforms to Protocol 44 | 45 | @interface ALCPlugFix : NSObject 46 | @end; 47 | @implementation ALCPlugFix 48 | - (id)init 49 | { 50 | self = [super init]; 51 | if (self) { 52 | // Do here what you needs to be done to start things 53 | 54 | // sleep wake 55 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 56 | selector: @selector(receiveWakeNote:) 57 | name: NSWorkspaceDidWakeNotification object: nil]; 58 | // screen unlock 59 | [[NSDistributedNotificationCenter defaultCenter] addObserver: self 60 | selector: @selector(receiveWakeNote:) 61 | name: @"com.apple.screenIsUnlocked" object: nil]; 62 | // screen saver end 63 | [[NSDistributedNotificationCenter defaultCenter] addObserver: self 64 | selector: @selector(receiveWakeNote:) 65 | name: @"com.apple.screensaver.didstop" object: nil]; 66 | // Screen wake 67 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 68 | selector: @selector(receiveWakeNote:) 69 | name: NSWorkspaceScreensDidWakeNotification object: nil]; 70 | // Switch to other user 71 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 72 | selector: @selector(receiveWakeNote:) 73 | name: NSWorkspaceSessionDidResignActiveNotification object: nil]; 74 | // Switch back to current user 75 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self 76 | selector: @selector(receiveWakeNote:) 77 | name: NSWorkspaceSessionDidBecomeActiveNotification object: nil]; 78 | } 79 | return self; 80 | } 81 | 82 | 83 | - (void)dealloc 84 | { 85 | // Do here what needs to be done to shut things down 86 | //[super dealloc]; 87 | } 88 | 89 | - (void)performWork 90 | { 91 | // This method is called periodically to perform some routine work 92 | NSLog(@"Performing periodical work"); 93 | // fixAudio(); 94 | 95 | } 96 | - (void) receiveWakeNote: (NSNotification*) note 97 | { 98 | NSLog(@"receiveSleepNote: %@", [note name]); 99 | NSLog(@"Wake detected"); 100 | fixAudio(); 101 | } 102 | 103 | 104 | @end 105 | 106 | # pragma mark Setup the daemon 107 | 108 | // Seconds runloop runs before performing work in second. 109 | #define kRunLoopWaitTime 14400.0 // 4hour 110 | 111 | BOOL keepRunning = TRUE; 112 | CFRunLoopRef runLoopRef; 113 | 114 | void sigHandler(int signo) 115 | { 116 | NSLog(@"sigHandler: Received signal %d", signo); 117 | 118 | switch (signo) { 119 | case SIGTERM: 120 | case SIGKILL: 121 | case SIGQUIT: 122 | case SIGHUP: 123 | case SIGINT: 124 | // Now handle more signal to quit 125 | NSLog(@"Exiting..."); 126 | keepRunning = FALSE; 127 | CFRunLoopStop(CFRunLoopGetCurrent()); // Kill current thread so we don't need to wait until next runloop call 128 | break; 129 | default: 130 | break; 131 | } 132 | } 133 | 134 | void fixAudio(){ 135 | NSLog(@"Fixing..."); 136 | NSString *output1 = [[binPrefix stringByAppendingString:@"hda-verb 0x1a SET_PIN_WIDGET_CONTROL 0x24"] runAsCommand]; 137 | } 138 | 139 | 140 | 141 | 142 | 143 | int main(int argc, const char * argv[]) { 144 | @autoreleasepool { 145 | 146 | NSLog(@"ALCPlugFix v1.7"); 147 | keepRunning = false; 148 | 149 | binPrefix = @""; 150 | 151 | signal(SIGHUP, sigHandler); 152 | signal(SIGTERM, sigHandler); 153 | signal(SIGKILL, sigHandler); 154 | signal(SIGQUIT, sigHandler); 155 | signal(SIGINT, sigHandler); 156 | 157 | ALCPlugFix *task = [[ALCPlugFix alloc] init]; 158 | 159 | // Check hda-verb location 160 | NSFileManager *filemgr; 161 | filemgr = [[NSFileManager alloc] init]; 162 | 163 | if ([filemgr fileExistsAtPath:@"./hda-verb"]){ 164 | // hda-verb at work dir 165 | NSLog(@"Found had-verb in work dir"); 166 | binPrefix = [filemgr.currentDirectoryPath stringByAppendingString:@"/"]; 167 | }else 168 | NSLog(@"Current Directory %@", filemgr.currentDirectoryPath); 169 | 170 | NSLog(@"Headphones daemon running!"); 171 | // Audio Listener setup 172 | AudioDeviceID defaultDevice = 0; 173 | UInt32 defaultSize = sizeof(AudioDeviceID); 174 | 175 | const AudioObjectPropertyAddress defaultAddr = { 176 | kAudioHardwarePropertyDefaultOutputDevice, 177 | kAudioObjectPropertyScopeGlobal, 178 | kAudioObjectPropertyElementMaster 179 | }; 180 | 181 | 182 | AudioObjectPropertyAddress sourceAddr; 183 | sourceAddr.mSelector = kAudioDevicePropertyDataSource; 184 | sourceAddr.mScope = kAudioDevicePropertyScopeOutput; 185 | sourceAddr.mElement = kAudioObjectPropertyElementMaster; 186 | 187 | AudioObjectPropertyListenerBlock audioObjectPropertyListenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses) { 188 | // Audio device have changed 189 | NSLog(@"Audio device changed!"); 190 | fixAudio(); 191 | }; 192 | 193 | OSStatus osStatus; 194 | 195 | do { 196 | AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultAddr, 0, NULL, &defaultSize, &defaultDevice); 197 | osStatus = AudioObjectAddPropertyListenerBlock(defaultDevice, &sourceAddr, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), audioObjectPropertyListenerBlock); 198 | 199 | if (osStatus != 0){ 200 | // OS Status 560947818 is 'normal' as we are trying to hook audio object before login screen. 201 | NSLog(@"ERROR: Something went wrong! Failed to add Audio Listener!"); 202 | NSLog(@"OS Status: %d",osStatus); 203 | NSLog(@"Waiting 7 second"); 204 | sleep(7); 205 | } else 206 | NSLog(@"Correctly added Audio Listener!"); 207 | 208 | }while(osStatus!=0); 209 | 210 | // Fix at boot 211 | fixAudio(); 212 | do{ 213 | [task performWork]; 214 | CFRunLoopRunInMode(kCFRunLoopDefaultMode, kRunLoopWaitTime, false); 215 | }while (keepRunning); 216 | // [task release]; 217 | 218 | OSStatus removeStatus = AudioObjectRemovePropertyListenerBlock(defaultDevice, &sourceAddr, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),audioObjectPropertyListenerBlock); 219 | NSLog(@"Listener removed with status: %d",removeStatus); 220 | NSLog(@"Daemon exited"); 221 | } 222 | return 0; 223 | } 224 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | KeepAlive 6 | 7 | Label 8 | good.win.ALCPlugFix 9 | ProgramArguments 10 | 11 | /Library/MyDaemon/Daemon/ 12 | 13 | RunAtLoad 14 | 15 | ServiceIPC 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | ALCPlugFix 2 | ---------- 3 | 4 | This is an improved version of ALCPlugFix from [goodwin](https://github.com/goodwin/ALCPlugFix). 5 | 6 | The original and this fork tries to fix headphone audio power state issue in non Apple sound card in macOS. 7 | 8 | The improvement include: 9 | 10 | - Refactor 11 | - Add listener when sleep/wake 12 | - Fix on sleep wake 13 | - Let you choose `hda-verb` so it don't need be in `$PATH` 14 | - Enable launching as LauchDaemon 15 | - Bug fix 16 | - Install.sh script with update support 17 | - Uninstall.sh to uninstall ALCPlugFix 18 | - macOS Catalina support 19 | 20 | Install 21 | ------- 22 | By default it's code command is for Lenovo ThinkPad(s) with Realtek ALC3232 Audio Codec with Combo Jack, you may need to change that in `fixAudio` function. 23 | 24 | Running `sh ./install.sh` will install to `/user/local/bin`. 25 | 26 | By default it search `hda-verb` in current work directory, if not found it will search in `$PATH` _(May not work when it is running from LaunchDaemon because it is using as root)_. 27 | 28 | Compatible Laptops 29 | ------------------ 30 | - Lenovo ThinkPad T440P 31 | - Lenovo ThinkPad T440 32 | - Lenovo ThinkPad T440S 33 | - Lenovo ThinkPad L440 34 | - Lenovo ThinkPad X240 35 | 36 | Build 37 | ----- 38 | `xcodebuild -target ALCPlugFix` 39 | 40 | Debug 41 | ----- 42 | 43 | Add following to launchDaemon file to log to `/tmp/ALCPlugFix.log`, _(or use `log stream`)_ 44 | 45 | ``` 46 | StandardOutPath 47 | /tmp/ALCPlugFix.log 48 | StandardErrorPath 49 | /tmp/ALCPlugFix.log 50 | ``` 51 | 52 | Credits 53 | ----- 54 | 55 | - Goodwin for creating the Software 56 | - Menchen for the refactoring and new features 57 | - Joshuaseltzer for creating new install.sh and uninstall.sh 58 | - Sniki for maintaining the software 59 | -------------------------------------------------------------------------------- /good.win.ALCPlugFix.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | KeepAlive 6 | 7 | Label 8 | good.win.ALCPlugFix 9 | ProgramArguments 10 | 11 | /usr/local/bin/ALCPlugFix 12 | 13 | RunAtLoad 14 | 15 | ServiceIPC 16 | 17 | 18 | WorkingDirectory 19 | /usr/local/bin/ 20 | 21 | 22 | -------------------------------------------------------------------------------- /hda-verb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sniki/ALCPlugFix/b73ff371ed1597d485dd10f11e32ad0d80bbe409/hda-verb -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DAEMON_PATH=/Library/LaunchDaemons/ 4 | BIN_PATH=/usr/local/bin/ 5 | DAEMON_FILE=good.win.ALCPlugFix.plist 6 | VERB_FILE=hda-verb 7 | FIX_FILE=ALCPlugFix 8 | 9 | echo "Installing ALCPlugFix v1.7" 10 | 11 | # check if the directory "usr/local/bin" exist, if not then create the directory 12 | 13 | if [ ! -d "$BIN_PATH" ] ; then 14 | mkdir "$BIN_PATH" ; 15 | fi 16 | 17 | # stop the daemon if it's already running 18 | if sudo launchctl list | grep --quiet ALCPlugFix; then 19 | echo "Stopping existing ALCPlugFix daemon." 20 | sudo launchctl unload $DAEMON_PATH$DAEMON_FILE 21 | fi 22 | 23 | # copy over the files to their respective locations (overwrite automatically if files exist) 24 | 25 | sudo cp -rf ALCPlugFix $BIN_PATH 26 | sudo cp -f hda-verb $BIN_PATH 27 | sudo cp -f good.win.ALCPlugFix.plist $DAEMON_PATH 28 | 29 | # set permissions and ownership 30 | sudo chmod 755 $BIN_PATH$FIX_FILE 31 | sudo chown $USER:admin $BIN_PATH$FIX_FILE 32 | sudo chmod 755 $BIN_PATH$VERB_FILE 33 | sudo chown $USER:admin $BIN_PATH$VERB_FILE 34 | sudo chmod 644 $DAEMON_PATH$DAEMON_FILE 35 | sudo chown root:wheel $DAEMON_PATH$DAEMON_FILE 36 | 37 | # load and start the daemon 38 | sudo launchctl load -w $DAEMON_PATH$DAEMON_FILE 39 | 40 | echo "Done!" 41 | exit 0 42 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Uninstalling ALCPlugFix. Root user is required." 4 | 5 | sudo rm /usr/local/bin/ALCPlugFix 6 | sudo rm /usr/local/bin/hda-verb 7 | sudo launchctl unload -w /Library/LaunchDaemons/good.win.ALCPlugFix.plist 8 | sudo launchctl remove good.win.ALCPlugFix 9 | sudo rm /Library/LaunchDaemons/good.win.ALCPlugFix.plist 10 | 11 | echo "Done!" 12 | exit 0 13 | --------------------------------------------------------------------------------