2012-08-20 21:34:54 +02:00
/ *
* FanControl
*
2012-08-21 00:05:39 +02:00
* Copyright ( c ) 2006 -2012 Hendrik Holtmann
2013-12-21 09:26:27 -05:00
* Portions Copyright ( c ) 2013 Michael Wilber
*
2012-08-20 21:34:54 +02:00
* FanControl . m - MacBook ( Pro ) FanControl application
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 -1307 USA
* /
# import "FanControl.h"
# import "MachineDefaults.h"
# import < Security / Authorization . h >
# import < Security / AuthorizationDB . h >
# import < Security / AuthorizationTags . h >
# import < Sparkle / SUUpdater . h >
# import "SystemVersion.h"
2012-08-21 12:57:30 +02:00
@ interface FanControl ( )
2014-03-27 12:38:43 -04:00
+ ( void ) copyMachinesIfNecessary ;
2014-10-21 17:57:58 +02:00
@ property ( NS_NONATOMIC _IOSONLY , getter = isInAutoStart , readonly ) BOOL inAutoStart ;
2014-03-27 12:38:43 -04:00
- ( void ) setStartAtLogin : ( BOOL ) enabled ;
+ ( void ) checkRightStatus : ( OSStatus ) status ;
2012-08-21 12:57:30 +02:00
@ end
2012-08-20 21:34:54 +02:00
@ implementation FanControl
2013-12-21 09:26:27 -05:00
// Number of fans reported by the hardware .
int g_numFans = 0 ;
2012-08-20 21:34:54 +02:00
2018-08-10 14:08:35 +02:00
2013-12-21 09:26:27 -05:00
NSUserDefaults * defaults ;
2012-08-20 21:34:54 +02:00
# pragma mark * * Init - Methods * *
+ ( void ) initialize {
// avoid Zombies when starting external app
signal ( SIGCHLD , SIG_IGN ) ;
[ FanControl copyMachinesIfNecessary ] ;
// check owner and suid rights
[ FanControl setRights ] ;
// talk to smc
[ smcWrapper init ] ;
// app in foreground for update notifications
[ [ NSApplication sharedApplication ] activateIgnoringOtherApps : YES ] ;
}
+ ( void ) copyMachinesIfNecessary
{
NSString * path = [ [ [ NSFileManager defaultManager ] applicationSupportDirectory ] stringByAppendingPathComponent : @ "Machines.plist" ] ;
if ( ! [ [ NSFileManager defaultManager ] fileExistsAtPath : path ] ) {
[ [ NSFileManager defaultManager ] copyItemAtPath : [ [ NSBundle mainBundle ] pathForResource : @ "Machines" ofType : @ "plist" ] toPath : path error : nil ] ;
}
}
- ( void ) upgradeFavorites
{
// upgrade favorites
NSArray * rfavorites = [ FavoritesController arrangedObjects ] ;
int j ;
int i ;
for ( i = 0 ; i < [ rfavorites count ] ; i + + )
{
BOOL selected = NO ;
2016-10-16 18:28:42 +02:00
NSArray * fans = rfavorites [ i ] [ PREF_FAN _ARRAY ] ;
2012-08-20 21:34:54 +02:00
for ( j = 0 ; j < [ fans count ] ; j + + ) {
2016-10-16 18:28:42 +02:00
if ( [ fans [ j ] [ PREF_FAN _SHOWMENU ] boolValue ] = = YES ) {
2012-08-20 21:34:54 +02:00
selected = YES ;
}
}
if ( selected = = NO ) {
2016-10-16 18:28:42 +02:00
rfavorites [ i ] [ PREF_FAN _ARRAY ] [ 0 ] [ PREF_FAN _SHOWMENU ] = @ YES ;
2012-08-20 21:34:54 +02:00
}
}
}
- ( void ) awakeFromNib {
2013-12-21 09:26:27 -05:00
2012-08-20 21:34:54 +02:00
pw = [ [ Power alloc ] init ] ;
[ pw setDelegate : self ] ;
[ pw registerForSleepWakeNotification ] ;
[ pw registerForPowerChange ] ;
2014-10-20 16:33:31 +02:00
2014-10-20 17:30:59 +02:00
// load defaults
[ DefaultsController setAppliesImmediately : NO ] ;
2012-08-20 21:34:54 +02:00
mdefaults = [ [ MachineDefaults alloc ] init : nil ] ;
2014-10-21 17:57:58 +02:00
self . machineDefaultsDict = [ [ NSMutableDictionary alloc ] initWithDictionary : [ mdefaults get_machine _defaults ] ] ;
2012-08-20 21:34:54 +02:00
2014-10-21 17:57:58 +02:00
NSMutableArray * favorites = [ [ NSMutableArray alloc ] init ] ;
2016-10-16 18:28:42 +02:00
NSMutableDictionary * defaultFav = [ [ NSMutableDictionary alloc ] initWithObjectsAndKeys : @ "Default" , PREF_FAN _TITLE ,
[ NSKeyedUnarchiver unarchiveObjectWithData : [ NSKeyedArchiver archivedDataWithRootObject : [ [ mdefaults get_machine _defaults ] objectForKey : @ "Fans" ] ] ] , PREF_FAN _ARRAY , nil ] ;
2014-10-21 17:57:58 +02:00
[ favorites addObject : defaultFav ] ;
2012-08-20 21:34:54 +02:00
NSRange range = [ [ MachineDefaults computerModel ] rangeOfString : @ "MacBook" ] ;
if ( range . length > 0 ) {
// for macbooks add a second default
2016-10-16 18:28:42 +02:00
NSMutableDictionary * higherFav = [ [ NSMutableDictionary alloc ] initWithObjectsAndKeys : @ "Higher RPM" , PREF_FAN _TITLE ,
[ NSKeyedUnarchiver unarchiveObjectWithData : [ NSKeyedArchiver archivedDataWithRootObject : [ [ mdefaults get_machine _defaults ] objectForKey : @ "Fans" ] ] ] , PREF_FAN _ARRAY , nil ] ;
2014-10-21 17:57:58 +02:00
for ( NSUInteger i = 0 ; i < [ _machineDefaultsDict [ @ "Fans" ] count ] ; i + + ) {
2016-10-16 18:28:42 +02:00
int min_value = ( [ [ [ [ _machineDefaultsDict objectForKey : @ "Fans" ] objectAtIndex : i ] objectForKey : PREF_FAN _MINSPEED ] intValue ] ) * 2 ;
[ [ [ higherFav objectForKey : PREF_FAN _ARRAY ] objectAtIndex : i ] setObject : [ NSNumber numberWithInt : min_value ] forKey : PREF_FAN _SELSPEED ] ;
2012-08-20 21:34:54 +02:00
}
2014-10-21 17:57:58 +02:00
[ favorites addObject : higherFav ] ;
}
2012-08-20 21:34:54 +02:00
// sync option for Macbook Pro ' s
NSRange range_mbp = [ [ MachineDefaults computerModel ] rangeOfString : @ "MacBookPro" ] ;
2014-10-21 17:57:58 +02:00
if ( range_mbp . length > 0 && [ _machineDefaultsDict [ @ "Fans" ] count ] = = 2 ) {
2012-08-20 21:34:54 +02:00
[ sync setHidden : NO ] ;
}
// load user defaults
defaults = [ NSUserDefaults standardUserDefaults ] ;
[ defaults registerDefaults :
[ NSMutableDictionary dictionaryWithObjectsAndKeys :
2016-10-16 18:28:42 +02:00
@ 0 , PREF_TEMP _UNIT ,
@ 0 , PREF_SELECTION _DEFAULT ,
@ NO , PREF_AUTOSTART _ENABLED ,
@ NO , PREF_AUTOMATIC _CHANGE ,
@ 0 , PREF_BATTERY _SELECTION ,
@ 0 , PREF_AC _SELECTION ,
@ 0 , PREF_CHARGING _SELECTION ,
@ 0 , PREF_MENU _DISPLAYMODE ,
2022-12-02 23:34:35 +00:00
# if TARGET_CPU _ARM64
2022-12-03 14:47:15 +00:00
@ "Tp0D" , PREF_TEMPERATURE _SENSOR ,
2022-12-02 23:34:35 +00:00
# else
@ "TC0D" , PREF_TEMPERATURE _SENSOR ,
# endif
2016-10-16 18:28:42 +02:00
@ 0 , PREF_NUMBEROF _LAUNCHES ,
@ NO , PREF_DONATIONMESSAGE _DISPLAY ,
[ NSArchiver archivedDataWithRootObject : [ NSColor blackColor ] ] , PREF_MENU _TEXTCOLOR ,
favorites , PREF_FAVORITES _ARRAY ,
2012-08-20 21:34:54 +02:00
nil ] ] ;
2013-12-21 09:26:27 -05:00
g_numFans = [ smcWrapper get_fan _num ] ;
2012-08-20 21:34:54 +02:00
s_menus = [ [ NSMutableArray alloc ] init ] ;
int i ;
2013-12-21 09:26:27 -05:00
for ( i = 0 ; i < g_numFans ; i + + ) {
2012-08-20 21:34:54 +02:00
NSMenuItem * mitem = [ [ NSMenuItem alloc ] initWithTitle : [ NSString stringWithFormat : @ "Fan: %d" , i ] action : NULL keyEquivalent : @ "" ] ;
[ mitem setTag : ( i + 1 ) * 10 ] ;
[ s_menus insertObject : mitem atIndex : i ] ;
}
[ FavoritesController bind : @ "content"
toObject : [ NSUserDefaultsController sharedUserDefaultsController ]
2016-10-16 18:28:42 +02:00
withKeyPath : [ @ "values." stringByAppendingString : PREF_FAVORITES _ARRAY ]
2012-08-20 21:34:54 +02:00
options : nil ] ;
[ FavoritesController setEditable : YES ] ;
// set slider sync - only for MBP
for ( i = 0 ; i < [ [ FavoritesController arrangedObjects ] count ] ; i + + ) {
2016-10-16 18:28:42 +02:00
if ( [ [ FavoritesController arrangedObjects ] [ i ] [ PREF_FAN _SYNC ] boolValue ] = = YES ) {
2012-08-20 21:34:54 +02:00
[ FavoritesController setSelectionIndex : i ] ;
2016-10-16 18:28:42 +02:00
[ self syncBinder : [ [ FavoritesController arrangedObjects ] [ i ] [ PREF_FAN _SYNC ] boolValue ] ] ;
2012-08-20 21:34:54 +02:00
}
}
// init statusitem
[ self init_statusitem ] ;
[ programinfo setStringValue : [ NSString stringWithFormat : @ "%@ %@" , [ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "CFBundleName" ]
, [ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "CFBundleVersion" ] ] ] ;
//
[ copyright setStringValue : [ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "NSHumanReadableCopyright" ] ] ;
// power controls only available on portables
if ( range . length > 0 ) {
[ autochange setEnabled : true ] ;
} else {
[ autochange setEnabled : false ] ;
}
[ faqText replaceCharactersInRange : NSMakeRange ( 0 , 0 ) withRTF : [ NSData dataWithContentsOfFile : [ [ NSBundle mainBundle ] pathForResource : @ "F.A.Q" ofType : @ "rtf" ] ] ] ;
2016-10-16 18:28:42 +02:00
[ self apply_settings : nil controllerindex : [ [ defaults objectForKey : PREF_SELECTION _DEFAULT ] intValue ] ] ;
[ [ [ [ theMenu itemWithTag : 1 ] submenu ] itemAtIndex : [ [ defaults objectForKey : PREF_SELECTION _DEFAULT ] intValue ] ] setState : NSOnState ] ;
2012-08-20 21:34:54 +02:00
[ [ sliderCell dataCell ] setControlSize : NSSmallControlSize ] ;
[ self changeMenu : nil ] ;
// seting toolbar image
2014-10-20 16:33:31 +02:00
menu_image = [ [ NSImage alloc ] initWithContentsOfFile : [ [ NSBundle mainBundle ] pathForResource : @ "smc" ofType : @ "png" ] ] ;
menu_image _alt = [ [ NSImage alloc ] initWithContentsOfFile : [ [ NSBundle mainBundle ] pathForResource : @ "smcover" ofType : @ "png" ] ] ;
if ( [ menu_image respondsToSelector : @ selector ( setTemplate : ) ] ) {
[ menu_image setTemplate : YES ] ;
[ menu_image _alt setTemplate : YES ] ;
}
2012-08-20 21:34:54 +02:00
// add timer for reading to RunLoop
2013-12-21 09:26:27 -05:00
_readTimer = [ NSTimer scheduledTimerWithTimeInterval : 4.0 target : self selector : @ selector ( readFanData : ) userInfo : nil repeats : YES ] ;
2014-02-10 02:09:25 +01:00
if ( [ _readTimer respondsToSelector : @ selector ( setTolerance : ) ] ) {
[ _readTimer setTolerance : 2.0 ] ;
}
2012-08-20 21:34:54 +02:00
[ _readTimer fire ] ;
2014-10-21 17:57:58 +02:00
2012-08-20 21:34:54 +02:00
// autoapply settings if valid
[ self upgradeFavorites ] ;
// autostart
2016-10-16 18:28:42 +02:00
[ [ NSUserDefaults standardUserDefaults ] setValue : @ ( [ self isInAutoStart ] ) forKey : PREF_AUTOSTART _ENABLED ] ;
NSUInteger numLaunches = [ [ [ NSUserDefaults standardUserDefaults ] objectForKey : PREF_NUMBEROF _LAUNCHES ] integerValue ] ;
[ [ NSUserDefaults standardUserDefaults ] setObject : @ ( numLaunches + 1 ) forKey : PREF_NUMBEROF _LAUNCHES ] ;
if ( numLaunches ! = 0 && ( numLaunches % 3 = = 0 ) && ! [ [ [ NSUserDefaults standardUserDefaults ] objectForKey : PREF_DONATIONMESSAGE _DISPLAY ] boolValue ] ) {
2014-10-21 17:57:58 +02:00
[ self displayDonationMessage ] ;
}
2016-10-12 03:48:56 +02:00
[ [ NSDistributedNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( readFanData : ) name : @ "AppleInterfaceThemeChangedNotification" object : nil ] ;
2014-10-21 17:57:58 +02:00
}
- ( void ) displayDonationMessage
{
NSAlert * alert = [ NSAlert alertWithMessageText : NSLocalizedString ( @ "Consider a donation" , nil )
defaultButton : NSLocalizedString ( @ "Donate over Paypal" , nil ) alternateButton : NSLocalizedString ( @ "Never ask me again" , nil ) otherButton : NSLocalizedString ( @ "Remind me later" , nil )
informativeTextWithFormat : NSLocalizedString ( @ "smcFanControl keeps your Mac cool since 2006.\n\nIf smcFanControl is helfpul for you and you want to support further development, a small donation over Paypal is much appreciated." , nil ) ] ;
NSModalResponse code = [ alert runModal ] ;
if ( code = = NSAlertDefaultReturn ) {
[ self paypal : nil ] ;
2016-10-16 18:28:42 +02:00
[ [ NSUserDefaults standardUserDefaults ] setObject : @ ( YES ) forKey : PREF_DONATIONMESSAGE _DISPLAY ] ;
2014-10-21 17:57:58 +02:00
} else if ( code = = NSAlertAlternateReturn ) {
2016-10-16 18:28:42 +02:00
[ [ NSUserDefaults standardUserDefaults ] setObject : @ ( YES ) forKey : PREF_DONATIONMESSAGE _DISPLAY ] ;
2014-10-21 17:57:58 +02:00
}
2012-08-20 21:34:54 +02:00
}
- ( void ) init_statusitem {
2014-10-21 17:57:58 +02:00
statusItem = [ [ NSStatusBar systemStatusBar ] statusItemWithLength : NSVariableStatusItemLength ] ;
2012-08-20 21:34:54 +02:00
[ statusItem setMenu : theMenu ] ;
2014-10-20 16:33:31 +02:00
if ( [ statusItem respondsToSelector : @ selector ( button ) ] ) {
[ statusItem . button setTitle : @ "smc..." ] ;
} else {
[ statusItem setEnabled : YES ] ;
[ statusItem setHighlightMode : YES ] ;
[ statusItem setTitle : @ "smc..." ] ;
}
2012-08-20 21:34:54 +02:00
int i ;
for ( i = 0 ; i < [ s_menus count ] ; i + + ) {
2014-10-21 17:57:58 +02:00
[ theMenu insertItem : s_menus [ i ] atIndex : i ] ;
2012-08-20 21:34:54 +02:00
} ;
2013-12-25 09:47:10 -05:00
// Sign up for menuNeedsUpdate call
// so that the fan speeds in the menu can be updated
// only when needed .
[ theMenu setDelegate : self ] ;
2012-08-20 21:34:54 +02:00
}
# pragma mark * * Action - Methods * *
- ( IBAction ) loginItem : ( id ) sender {
if ( [ sender state ] = = NSOnState ) {
[ self setStartAtLogin : YES ] ;
} else {
[ self setStartAtLogin : NO ] ;
}
}
- ( IBAction ) add_favorite : ( id ) sender {
[ [ NSApplication sharedApplication ] beginSheet : newfavoritewindow
modalForWindow : mainwindow
modalDelegate : nil
didEndSelector : nil
contextInfo : nil ] ;
}
- ( IBAction ) close_favorite : ( id ) sender {
[ newfavoritewindow close ] ;
[ [ NSApplication sharedApplication ] endSheet : newfavoritewindow ] ;
}
- ( IBAction ) save_favorite : ( id ) sender {
MachineDefaults * msdefaults = [ [ MachineDefaults alloc ] init : nil ] ;
if ( [ [ newfavorite_title stringValue ] length ] > 0 ) {
2016-10-16 18:28:42 +02:00
NSMutableDictionary * toinsert = [ [ NSMutableDictionary alloc ] initWithObjectsAndKeys : [ newfavorite_title stringValue ] , @ "Title" , [ msdefaults get_machine _defaults ] [ @ "Fans" ] , PREF_FAN _ARRAY , nil ] ; // default as template
2014-10-21 17:57:58 +02:00
[ toinsert setValue : @ 0 forKey : @ "Standard" ] ;
2012-08-20 21:34:54 +02:00
[ FavoritesController addObject : toinsert ] ;
[ newfavoritewindow close ] ;
[ [ NSApplication sharedApplication ] endSheet : newfavoritewindow ] ;
}
[ self upgradeFavorites ] ;
}
- ( void ) check_deletion : ( id ) combo {
if ( [ FavoritesController selectionIndex ] = = [ [ defaults objectForKey : combo ] intValue ] ) {
2014-10-21 17:57:58 +02:00
[ defaults setObject : @ 0 forKey : combo ] ;
2012-08-20 21:34:54 +02:00
}
}
2014-02-23 17:13:43 +01:00
- ( void ) deleteAlertDidEnd : ( NSAlert * ) alert returnCode : ( NSInteger ) returnCode contextInfo : ( void * ) contextInfo ;
{
if ( returnCode = = 0 ) {
2012-08-20 21:34:54 +02:00
// delete favorite , but resets presets before
2016-10-16 18:28:42 +02:00
[ self check_deletion : PREF_BATTERY _SELECTION ] ;
[ self check_deletion : PREF_AC _SELECTION ] ;
[ self check_deletion : PREF_CHARGING _SELECTION ] ;
2014-02-23 17:13:43 +01:00
[ FavoritesController removeObjects : [ FavoritesController selectedObjects ] ] ;
2012-08-20 21:34:54 +02:00
}
}
2014-02-23 17:13:43 +01:00
- ( IBAction ) delete_favorite : ( id ) sender {
2014-10-21 17:57:58 +02:00
NSAlert * alert = [ NSAlert alertWithMessageText : NSLocalizedString ( @ "Delete favorite" , nil ) defaultButton : NSLocalizedString ( @ "No" , nil ) alternateButton : NSLocalizedString ( @ "Yes" , nil ) otherButton : nil informativeTextWithFormat : [ NSString stringWithFormat : NSLocalizedString ( @ "Do you really want to delete the favorite %@?" , nil ) , [ FavoritesController arrangedObjects ] [ [ FavoritesController selectionIndex ] ] [ @ "Title" ] ] ] ;
2014-02-23 17:13:43 +01:00
[ alert beginSheetModalForWindow : mainwindow modalDelegate : self didEndSelector : @ selector ( deleteAlertDidEnd : returnCode : contextInfo : ) contextInfo : NULL ] ;
}
2012-08-20 21:34:54 +02:00
2022-12-03 14:47:15 +00:00
- ( BOOL ) usesIOHIDForTemperature {
# if TARGET_CPU _ARM64
return [ [ MachineDefaults computerModel ] rangeOfString : @ "MacBookPro17" ] . length > 0 ;
# else
return false ;
# endif
}
2014-10-20 16:33:31 +02:00
2013-12-21 09:26:27 -05:00
// Called via a timer mechanism . This is where all the temp / RPM reading is done .
2012-08-20 21:34:54 +02:00
// reads fan data and updates the gui
2014-10-20 16:33:31 +02:00
- ( void ) readFanData : ( id ) caller {
2012-08-20 21:34:54 +02:00
2013-12-21 09:26:27 -05:00
int i = 0 ;
2012-08-20 21:34:54 +02:00
// on init handling
2014-10-21 17:57:58 +02:00
if ( _machineDefaultsDict = = nil ) {
2012-08-20 21:34:54 +02:00
return ;
}
2013-12-21 09:26:27 -05:00
2013-12-25 09:47:10 -05:00
// Determine what data is actually needed to keep the energy impact
// as low as possible .
bool bNeedTemp = false ;
bool bNeedRpm = false ;
2016-10-16 18:28:42 +02:00
const int menuBarSetting = [ [ defaults objectForKey : PREF_MENU _DISPLAYMODE ] intValue ] ;
2013-12-25 09:47:10 -05:00
switch ( menuBarSetting ) {
default :
case 1 :
bNeedTemp = true ;
bNeedRpm = true ;
break ;
case 2 :
bNeedTemp = true ;
bNeedRpm = true ;
break ;
case 3 :
bNeedTemp = true ;
bNeedRpm = false ;
break ;
case 4 :
bNeedTemp = false ;
bNeedRpm = true ;
2013-12-21 09:26:27 -05:00
break ;
}
2013-12-25 09:47:10 -05:00
NSString * temp = nil ;
NSString * fan = nil ;
float c_temp = 0.0 f ;
int selectedRpm = 0 ;
2013-12-21 09:26:27 -05:00
2013-12-25 09:47:10 -05:00
if ( bNeedRpm = = true ) {
// Read the current fan speed for the desired fan and format text for display in the menubar .
2016-10-16 18:28:42 +02:00
NSArray * fans = [ FavoritesController arrangedObjects ] [ [ FavoritesController selectionIndex ] ] [ PREF_FAN _ARRAY ] ;
2013-12-25 09:47:10 -05:00
for ( i = 0 ; i < g_numFans && i < [ fans count ] ; i + + )
{
2016-10-16 18:28:42 +02:00
if ( [ fans [ i ] [ PREF_FAN _SHOWMENU ] boolValue ] = = YES ) {
2013-12-25 09:47:10 -05:00
selectedRpm = [ smcWrapper get_fan _rpm : i ] ;
break ;
}
}
2014-10-21 17:57:58 +02:00
NSNumberFormatter * nc = [ [ NSNumberFormatter alloc ] init ] ;
2013-12-25 09:47:10 -05:00
// avoid jumping in menu bar
[ nc setFormat : @ "000;000;-000" ] ;
fan = [ NSString stringWithFormat : @ "%@rpm" , [ nc stringForObjectValue : [ NSNumber numberWithFloat : selectedRpm ] ] ] ;
}
2013-12-21 09:26:27 -05:00
2013-12-25 09:47:10 -05:00
if ( bNeedTemp = = true ) {
// Read current temperature and format text for the menubar .
2022-12-03 14:47:15 +00:00
if ( [ self usesIOHIDForTemperature ] ) {
c_temp = [ IOHIDSensor getSOCTemperature ] ;
} else {
c_temp = [ smcWrapper get_maintemp ] ;
}
2013-12-25 09:47:10 -05:00
2016-10-16 18:28:42 +02:00
if ( [ [ defaults objectForKey : PREF_TEMP _UNIT ] intValue ] = = 0 ) {
2014-10-21 17:57:58 +02:00
temp = [ NSString stringWithFormat : @ "%@%CC" , @ ( c_temp ) , ( unsigned short ) 0 xb0 ] ;
2013-12-25 09:47:10 -05:00
} else {
2014-10-21 17:57:58 +02:00
NSNumberFormatter * ncf = [ [ NSNumberFormatter alloc ] init ] ;
2013-12-25 09:47:10 -05:00
[ ncf setFormat : @ "00;00;-00" ] ;
2014-10-21 17:57:58 +02:00
temp = [ NSString stringWithFormat : @ "%@%CF" , [ ncf stringForObjectValue : [ @ ( c_temp ) celsius_fahrenheit ] ] , ( unsigned short ) 0 xb0 ] ;
2013-12-25 09:47:10 -05:00
}
}
2013-12-21 09:26:27 -05:00
2013-12-25 09:47:10 -05:00
// Update the temp and / or fan speed text in the menubar .
NSMutableAttributedString * s_status = nil ;
NSMutableParagraphStyle * paragraphStyle = nil ;
2013-12-21 09:26:27 -05:00
2016-10-16 18:28:42 +02:00
NSColor * menuColor = ( NSColor * ) [ NSUnarchiver unarchiveObjectWithData : [ defaults objectForKey : PREF_MENU _TEXTCOLOR ] ] ;
2014-10-20 16:33:31 +02:00
BOOL setColor = NO ;
if ( ! ( [ [ menuColor colorUsingColorSpaceName :
NSCalibratedWhiteColorSpace ] whiteComponent ] = = 0.0 ) || ! [ statusItem respondsToSelector : @ selector ( button ) ] ) setColor = YES ;
2016-10-12 03:48:56 +02:00
NSString * osxMode = [ [ NSUserDefaults standardUserDefaults ] stringForKey : @ "AppleInterfaceStyle" ] ;
if ( osxMode && ! setColor ) {
menuColor = [ NSColor whiteColor ] ;
setColor = YES ;
}
2013-12-25 09:47:10 -05:00
switch ( menuBarSetting ) {
default :
case 1 : {
int fsize = 0 ;
NSString * add = nil ;
if ( menuBarSetting = = 0 ) {
add = @ "\n" ;
fsize = 9 ;
[ statusItem setLength : 53 ] ;
} else {
add = @ " " ;
fsize = 11 ;
[ statusItem setLength : 96 ] ;
}
s_status = [ [ NSMutableAttributedString alloc ] initWithString : [ NSString stringWithFormat : @ "%@%@%@" , temp , add , fan ] ] ;
paragraphStyle = [ [ NSParagraphStyle defaultParagraphStyle ] mutableCopy ] ;
[ paragraphStyle setAlignment : NSLeftTextAlignment ] ;
[ s_status addAttribute : NSFontAttributeName value : [ NSFont fontWithName : @ "Lucida Grande" size : fsize ] range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
[ s_status addAttribute : NSParagraphStyleAttributeName value : paragraphStyle range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
2021-01-10 21:52:26 +00:00
if ( menuBarSetting = = 0 )
[ s_status addAttribute : NSBaselineOffsetAttributeName value : [ NSNumber numberWithFloat : -6 ] range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
2014-10-20 16:33:31 +02:00
if ( setColor ) [ s_status addAttribute : NSForegroundColorAttributeName value : menuColor range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
2016-10-12 03:48:56 +02:00
2014-10-20 16:33:31 +02:00
if ( [ statusItem respondsToSelector : @ selector ( button ) ] ) {
[ statusItem . button setAttributedTitle : s_status ] ;
[ statusItem . button setImage : nil ] ;
[ statusItem . button setAlternateImage : nil ] ;
} else {
[ statusItem setAttributedTitle : s_status ] ;
[ statusItem setImage : nil ] ;
[ statusItem setAlternateImage : nil ] ;
}
2013-12-25 09:47:10 -05:00
break ;
}
case 2 :
// TODO : Big waste of energy to update this tooltip every X seconds when the user
// is unlikely to hover the smcFanControl icon over and over again .
[ statusItem setLength : 26 ] ;
2014-10-20 16:33:31 +02:00
if ( [ statusItem respondsToSelector : @ selector ( button ) ] ) {
[ statusItem . button setTitle : nil ] ;
[ statusItem . button setToolTip : [ NSString stringWithFormat : @ "%@\n%@" , temp , fan ] ] ;
[ statusItem . button setImage : menu_image ] ;
[ statusItem . button setAlternateImage : menu_image _alt ] ;
} else {
[ statusItem setTitle : nil ] ;
[ statusItem setToolTip : [ NSString stringWithFormat : @ "%@\n%@" , temp , fan ] ] ;
[ statusItem setImage : menu_image ] ;
[ statusItem setAlternateImage : menu_image _alt ] ;
}
2013-12-25 09:47:10 -05:00
break ;
case 3 :
[ statusItem setLength : 46 ] ;
s_status = [ [ NSMutableAttributedString alloc ] initWithString : [ NSString stringWithFormat : @ "%@" , temp ] ] ;
[ s_status addAttribute : NSFontAttributeName value : [ NSFont fontWithName : @ "Lucida Grande" size : 12 ] range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
2014-10-20 16:33:31 +02:00
if ( setColor ) [ s_status addAttribute : NSForegroundColorAttributeName value : menuColor range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
if ( [ statusItem respondsToSelector : @ selector ( button ) ] ) {
[ statusItem . button setAttributedTitle : s_status ] ;
[ statusItem . button setImage : nil ] ;
[ statusItem . button setAlternateImage : nil ] ;
} else {
[ statusItem setAttributedTitle : s_status ] ;
[ statusItem setImage : nil ] ;
[ statusItem setAlternateImage : nil ] ;
}
2013-12-25 09:47:10 -05:00
break ;
case 4 :
[ statusItem setLength : 65 ] ;
s_status = [ [ NSMutableAttributedString alloc ] initWithString : [ NSString stringWithFormat : @ "%@" , fan ] ] ;
[ s_status addAttribute : NSFontAttributeName value : [ NSFont fontWithName : @ "Lucida Grande" size : 12 ] range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
2014-10-20 16:33:31 +02:00
if ( setColor ) [ s_status addAttribute : NSForegroundColorAttributeName value : menuColor range : NSMakeRange ( 0 , [ s_status length ] ) ] ;
if ( [ statusItem respondsToSelector : @ selector ( button ) ] ) {
[ statusItem . button setAttributedTitle : s_status ] ;
[ statusItem . button setImage : nil ] ;
[ statusItem . button setAlternateImage : nil ] ;
} else {
[ statusItem setAttributedTitle : s_status ] ;
[ statusItem setImage : nil ] ;
[ statusItem setAlternateImage : nil ] ;
}
2013-12-25 09:47:10 -05:00
break ;
}
2013-12-21 09:26:27 -05:00
2012-08-20 21:34:54 +02:00
}
- ( IBAction ) savePreferences : ( id ) sender {
[ ( NSUserDefaultsController * ) DefaultsController save : sender ] ;
2016-10-16 18:28:42 +02:00
[ defaults setValue : [ FavoritesController content ] forKey : PREF_FAVORITES _ARRAY ] ;
2012-08-20 21:34:54 +02:00
[ defaults synchronize ] ;
[ mainwindow close ] ;
[ self apply_settings : sender controllerindex : [ FavoritesController selectionIndex ] ] ;
undo_dic = [ NSDictionary dictionaryWithDictionary : [ defaults dictionaryRepresentation ] ] ;
}
- ( IBAction ) closePreferences : ( id ) sender {
[ mainwindow close ] ;
[ DefaultsController revert : sender ] ;
}
2022-04-07 23:27:31 +01:00
- ( void ) setFansToAuto : ( bool ) is_auto {
2022-12-03 14:47:15 +00:00
for ( int fan_index = 0 ; fan_index < [ [ FavoritesController arrangedObjects ] [ 0 ] [ PREF_FAN _ARRAY ] count ] ; fan_index + + ) {
[ self setFanToAuto : fan_index is_auto : is_auto ] ;
}
2022-04-07 23:24:39 +01:00
}
- ( void ) setFanToAuto : ( int ) fan_index is_auto : ( bool ) is_auto {
2022-12-03 14:47:15 +00:00
[ smcWrapper setKey_external : [ NSString stringWithFormat : @ "F%dMd" , fan_index ] value : is_auto ? @ "00" : @ "01" ] ;
2022-04-07 23:24:39 +01:00
}
2012-08-20 21:34:54 +02:00
// set the new fan settings
- ( void ) apply_settings : ( id ) sender controllerindex : ( int ) cIndex {
int i ;
[ FanControl setRights ] ;
[ FavoritesController setSelectionIndex : cIndex ] ;
2018-08-10 14:08:35 +02:00
2020-07-18 16:25:46 +07:00
for ( i = 0 ; i < [ [ FavoritesController arrangedObjects ] [ cIndex ] [ PREF_FAN _ARRAY ] count ] ; i + + ) {
int fan_mode = [ smcWrapper get_mode : i ] ;
// Auto / forced mode is not available
if ( fan_mode < 0 ) {
[ smcWrapper setKey_external : [ NSString stringWithFormat : @ "F%dMn" , i ] value : [ [ FanController arrangedObjects ] [ i ] [ PREF_FAN _SELSPEED ] tohex ] ] ;
} else {
2018-11-07 21:29:54 +07:00
bool is_auto = [ [ FanController arrangedObjects ] [ i ] [ PREF_FAN _AUTO ] boolValue ] ;
2022-04-07 23:24:39 +01:00
[ self setFanToAuto : i is_auto : is_auto ] ;
2018-08-10 14:08:35 +02:00
float f_val = [ [ FanController arrangedObjects ] [ i ] [ PREF_FAN _SELSPEED ] floatValue ] ;
uint8 * vals = ( uint8 * ) & f_val ;
// NSString str_val = ;
[ smcWrapper setKey_external : [ NSString stringWithFormat : @ "F%dTg" , i ] value : [ NSString stringWithFormat : @ "%02x%02x%02x%02x" , vals [ 0 ] , vals [ 1 ] , vals [ 2 ] , vals [ 3 ] ] ] ;
}
}
2014-10-21 17:57:58 +02:00
NSMenu * submenu = [ [ NSMenu alloc ] init ] ;
2012-08-20 21:34:54 +02:00
for ( i = 0 ; i < [ [ FavoritesController arrangedObjects ] count ] ; i + + ) {
2014-10-21 17:57:58 +02:00
NSMenuItem * submenuItem = [ [ NSMenuItem alloc ] initWithTitle : [ FavoritesController arrangedObjects ] [ i ] [ @ "Title" ] action : @ selector ( apply_quickselect : ) keyEquivalent : @ "" ] ;
2012-08-20 21:34:54 +02:00
[ submenuItem setTag : i * 100 ] ; // for later manipulation
[ submenuItem setEnabled : YES ] ;
[ submenuItem setTarget : self ] ;
2014-10-21 17:57:58 +02:00
[ submenuItem setRepresentedObject : [ FavoritesController arrangedObjects ] [ i ] ] ;
2012-08-20 21:34:54 +02:00
[ submenu addItem : submenuItem ] ;
}
[ [ theMenu itemWithTag : 1 ] setSubmenu : submenu ] ;
for ( i = 0 ; i < [ [ [ theMenu itemWithTag : 1 ] submenu ] numberOfItems ] ; i + + ) {
[ [ [ [ theMenu itemWithTag : 1 ] submenu ] itemAtIndex : i ] setState : NSOffState ] ;
}
[ [ [ [ theMenu itemWithTag : 1 ] submenu ] itemAtIndex : cIndex ] setState : NSOnState ] ;
2016-10-16 18:28:42 +02:00
[ defaults setObject : @ ( cIndex ) forKey : PREF_SELECTION _DEFAULT ] ;
2012-08-20 21:34:54 +02:00
// change active setting display
2016-10-16 18:28:42 +02:00
[ [ theMenu itemWithTag : 1 ] setTitle : [ NSString stringWithFormat : @ "%@: %@" , NSLocalizedString ( @ "Active Setting" , nil ) , [ FavoritesController arrangedObjects ] [ [ FavoritesController selectionIndex ] ] [ PREF_FAN _TITLE ] ] ] ;
2012-08-20 21:34:54 +02:00
}
- ( void ) apply_quickselect : ( id ) sender {
int i ;
[ FanControl setRights ] ;
// set all others items to off
for ( i = 0 ; i < [ [ [ theMenu itemWithTag : 1 ] submenu ] numberOfItems ] ; i + + ) {
[ [ [ [ theMenu itemWithTag : 1 ] submenu ] itemAtIndex : i ] setState : NSOffState ] ;
}
[ sender setState : NSOnState ] ;
[ [ theMenu itemWithTag : 1 ] setTitle : [ NSString stringWithFormat : @ "%@: %@" , NSLocalizedString ( @ "Active Setting" , nil ) , [ sender title ] ] ] ;
[ self apply_settings : sender controllerindex : [ [ [ theMenu itemWithTag : 1 ] submenu ] indexOfItem : sender ] ] ;
}
- ( void ) terminate : ( id ) sender {
// get last active selection
[ defaults synchronize ] ;
2013-12-21 09:26:27 -05:00
[ smcWrapper cleanUp ] ;
2012-08-20 21:34:54 +02:00
[ _readTimer invalidate ] ;
[ pw deregisterForSleepWakeNotification ] ;
[ pw deregisterForPowerChange ] ;
[ [ NSApplication sharedApplication ] terminate : self ] ;
}
- ( IBAction ) syncSliders : ( id ) sender {
if ( [ sender state ] ) {
[ self syncBinder : YES ] ;
} else {
[ self syncBinder : NO ] ;
}
}
- ( IBAction ) changeMenu : ( id ) sender {
2016-10-16 18:28:42 +02:00
if ( [ [ [ [ NSUserDefaultsController sharedUserDefaultsController ] values ] valueForKey : PREF_MENU _DISPLAYMODE ] intValue ] = = 2 ) {
2012-08-20 21:34:54 +02:00
[ colorSelector setEnabled : NO ] ;
} else {
[ colorSelector setEnabled : YES ] ;
}
}
- ( IBAction ) menuSelect : ( id ) sender {
// deactivate all other radio buttons
int i ;
for ( i = 0 ; i < [ [ FanController arrangedObjects ] count ] ; i + + ) {
if ( i ! = [ sender selectedRow ] ) {
2016-10-16 18:28:42 +02:00
[ [ FanController arrangedObjects ] [ i ] setValue : @ NO forKey : PREF_FAN _SHOWMENU ] ;
2012-08-20 21:34:54 +02:00
}
}
2013-12-25 09:47:10 -05:00
}
// Called when user clicks on smcFanControl status bar item
// in the status area of the menubar . The fan speed
// menu items are now only updated here in order to
// reduce the energy impact of - readFanData .
- ( void ) menuNeedsUpdate : ( NSMenu * ) menu {
2014-10-21 17:57:58 +02:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
if ( theMenu = = menu ) {
if ( _machineDefaultsDict = = nil )
return ;
int i ;
for ( i = 0 ; i < g_numFans ; + + i ) {
NSString * fandesc = _machineDefaultsDict [ @ "Fans" ] [ i ] [ @ "Description" ] ;
[ [ theMenu itemWithTag : ( i + 1 ) * 10 ] setTitle : [ NSString stringWithFormat : @ "%@: %@ rpm" , fandesc , [ @ ( [ smcWrapper get_fan _rpm : i ] ) stringValue ] ] ] ;
}
2013-12-25 09:47:10 -05:00
}
2014-10-21 17:57:58 +02:00
} ) ;
2013-12-25 09:47:10 -05:00
}
2012-08-20 21:34:54 +02:00
# pragma mark * * Helper - Methods * *
// just a helper to bringt update - info - window to the front
- ( IBAction ) updateCheck : ( id ) sender {
2014-03-25 15:13:47 -04:00
SUUpdater * updater = [ [ SUUpdater alloc ] init ] ;
[ updater checkForUpdates : sender ] ;
2012-08-20 21:34:54 +02:00
[ [ NSApplication sharedApplication ] activateIgnoringOtherApps : YES ] ;
}
2014-10-30 16:51:29 +01:00
- ( void ) performReset
{
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
NSError * error ;
NSString * machinesPath = [ [ fileManager applicationSupportDirectory ] stringByAppendingPathComponent : @ "Machines.plist" ] ;
[ fileManager removeItemAtPath : machinesPath error : & error ] ;
if ( error ) {
NSLog ( @ "Error deleting %@" , machinesPath ) ;
}
error = nil ;
2018-08-10 14:08:35 +02:00
if ( [ [ MachineDefaults computerModel ] rangeOfString : @ "MacBookPro15" ] . location ! = NSNotFound ) {
2022-04-07 23:24:39 +01:00
[ self setFansToAuto : true ] ;
2018-08-10 14:08:35 +02:00
}
2014-10-30 16:51:29 +01:00
NSString * domainName = [ [ NSBundle mainBundle ] bundleIdentifier ] ;
[ [ NSUserDefaults standardUserDefaults ] removePersistentDomainForName : domainName ] ;
NSAlert * alert = [ NSAlert alertWithMessageText : NSLocalizedString ( @ "Shutdown required" , nil )
defaultButton : NSLocalizedString ( @ "OK" , nil ) alternateButton : nil otherButton : nil
informativeTextWithFormat : NSLocalizedString ( @ "Please shutdown your computer now to return to default fan settings." , nil ) ] ;
NSModalResponse code = [ alert runModal ] ;
if ( code = = NSAlertDefaultReturn ) {
[ [ NSApplication sharedApplication ] terminate : self ] ;
}
}
- ( IBAction ) resetSettings : ( id ) sender
{
NSAlert * alert = [ NSAlert alertWithMessageText : NSLocalizedString ( @ "Reset Settings" , nil )
defaultButton : NSLocalizedString ( @ "Yes" , nil ) alternateButton : NSLocalizedString ( @ "No" , nil ) otherButton : nil
informativeTextWithFormat : NSLocalizedString ( @ "Do you want to reset smcFanControl to default settings? Favorites will be deleted and fans will return to default speed." , nil ) ] ;
NSModalResponse code = [ alert runModal ] ;
if ( code = = NSAlertDefaultReturn ) {
[ self performReset ] ;
} else if ( code = = NSAlertAlternateReturn ) {
}
}
2012-08-20 21:34:54 +02:00
- ( IBAction ) visitHomepage : ( id ) sender {
2016-03-21 14:50:26 +01:00
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : @ "https://www.eidac.de/products" ] ] ;
2012-08-20 21:34:54 +02:00
}
- ( IBAction ) paypal : ( id ) sender {
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : @ "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=holtmann%40campus%2dvirtuell%2ede&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&bn=PP%2dDonationsBF&charset=UTF%2d8&country=US" ] ] ;
}
- ( void ) syncBinder : ( Boolean ) bind {
// in case plist is corrupt , don ' t bind
if ( [ [ FanController arrangedObjects ] count ] > 1 ) {
if ( bind = = YES ) {
2016-10-16 18:28:42 +02:00
[ [ FanController arrangedObjects ] [ 1 ] bind : PREF_FAN _SELSPEED toObject : [ FanController arrangedObjects ] [ 0 ] withKeyPath : PREF_FAN _SELSPEED options : nil ] ;
[ [ FanController arrangedObjects ] [ 0 ] bind : PREF_FAN _SELSPEED toObject : [ FanController arrangedObjects ] [ 1 ] withKeyPath : PREF_FAN _SELSPEED options : nil ] ;
2012-08-20 21:34:54 +02:00
} else {
2016-10-16 18:28:42 +02:00
[ [ FanController arrangedObjects ] [ 1 ] unbind : PREF_FAN _SELSPEED ] ;
[ [ FanController arrangedObjects ] [ 0 ] unbind : PREF_FAN _SELSPEED ] ;
2012-08-20 21:34:54 +02:00
}
}
}
# pragma mark * * Power Watchdog - Methods * *
2022-04-07 23:24:39 +01:00
- ( void ) systemWillSleep : ( id ) sender {
2022-12-02 23:34:35 +00:00
# if TARGET_CPU _ARM64
2022-12-03 14:47:15 +00:00
[ FanControl setRights ] ;
[ self setFansToAuto : true ] ;
2022-12-02 23:34:35 +00:00
# endif
2022-04-07 23:24:39 +01:00
}
2012-08-20 21:34:54 +02:00
- ( void ) systemDidWakeFromSleep : ( id ) sender {
2016-10-16 18:28:42 +02:00
[ self apply_settings : nil controllerindex : [ [ defaults objectForKey : PREF_SELECTION _DEFAULT ] intValue ] ] ;
2012-08-20 21:34:54 +02:00
}
- ( void ) powerChangeToBattery : ( id ) sender {
if ( [ [ defaults objectForKey : @ "AutomaticChange" ] boolValue ] = = YES ) {
2016-10-16 18:28:42 +02:00
[ self apply_settings : nil controllerindex : [ [ defaults objectForKey : PREF_BATTERY _SELECTION ] intValue ] ] ;
2012-08-20 21:34:54 +02:00
}
}
- ( void ) powerChangeToAC : ( id ) sender {
if ( [ [ defaults objectForKey : @ "AutomaticChange" ] boolValue ] = = YES ) {
2016-10-16 18:28:42 +02:00
[ self apply_settings : nil controllerindex : [ [ defaults objectForKey : PREF_AC _SELECTION ] intValue ] ] ;
2012-08-20 21:34:54 +02:00
}
}
- ( void ) powerChangeToACLoading : ( id ) sender {
if ( [ [ defaults objectForKey : @ "AutomaticChange" ] boolValue ] = = YES ) {
2016-10-16 18:28:42 +02:00
[ self apply_settings : nil controllerindex : [ [ defaults objectForKey : PREF_CHARGING _SELECTION ] intValue ] ] ;
2012-08-20 21:34:54 +02:00
}
}
# pragma mark -
# pragma mark Start - at - login control
- ( BOOL ) isInAutoStart
{
BOOL found = NO ;
LSSharedFileListRef loginItems = LSSharedFileListCreate ( kCFAllocatorDefault , kLSSharedFileListSessionLoginItems , / * options * / NULL ) ;
NSString * path = [ [ NSBundle mainBundle ] bundlePath ] ;
2014-10-21 17:57:58 +02:00
CFURLRef URLToToggle = ( __bridge CFURLRef ) [ NSURL fileURLWithPath : path ] ;
2014-03-25 15:13:47 -04:00
// LSSharedFileListItemRef existingItem = NULL ;
2012-08-20 21:34:54 +02:00
UInt32 seed = 0 U ;
2014-10-21 17:57:58 +02:00
NSArray * currentLoginItems = CFBridgingRelease ( LSSharedFileListCopySnapshot ( loginItems , & seed ) ) ;
2012-08-20 21:34:54 +02:00
for ( id itemObject in currentLoginItems ) {
2014-10-21 17:57:58 +02:00
LSSharedFileListItemRef item = ( __bridge LSSharedFileListItemRef ) itemObject ;
2012-08-20 21:34:54 +02:00
UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes ;
CFURLRef URL = NULL ;
OSStatus err = LSSharedFileListItemResolve ( item , resolutionFlags , & URL , / * outRef * / NULL ) ;
if ( err = = noErr ) {
Boolean foundIt = CFEqual ( URL , URLToToggle ) ;
CFRelease ( URL ) ;
if ( foundIt ) {
2014-03-25 15:13:47 -04:00
// existingItem = item ;
2012-08-20 21:34:54 +02:00
found = YES ;
break ;
}
}
}
return found ;
}
- ( void ) setStartAtLogin : ( BOOL ) enabled {
LSSharedFileListRef loginItems = LSSharedFileListCreate ( kCFAllocatorDefault , kLSSharedFileListSessionLoginItems , / * options * / NULL ) ;
NSString * path = [ [ NSBundle mainBundle ] bundlePath ] ;
OSStatus status ;
2014-10-21 17:57:58 +02:00
CFURLRef URLToToggle = ( __bridge CFURLRef ) [ NSURL fileURLWithPath : path ] ;
2012-08-20 21:34:54 +02:00
LSSharedFileListItemRef existingItem = NULL ;
UInt32 seed = 0 U ;
2014-10-21 17:57:58 +02:00
NSArray * currentLoginItems = CFBridgingRelease ( LSSharedFileListCopySnapshot ( loginItems , & seed ) ) ;
2012-08-20 21:34:54 +02:00
for ( id itemObject in currentLoginItems ) {
2014-10-21 17:57:58 +02:00
LSSharedFileListItemRef item = ( __bridge LSSharedFileListItemRef ) itemObject ;
2012-08-20 21:34:54 +02:00
UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes ;
CFURLRef URL = NULL ;
OSStatus err = LSSharedFileListItemResolve ( item , resolutionFlags , & URL , / * outRef * / NULL ) ;
if ( err = = noErr ) {
Boolean foundIt = CFEqual ( URL , URLToToggle ) ;
CFRelease ( URL ) ;
if ( foundIt ) {
existingItem = item ;
break ;
}
}
}
if ( enabled && ( existingItem = = NULL ) ) {
NSString * displayName = [ [ NSFileManager defaultManager ] displayNameAtPath : path ] ;
IconRef icon = NULL ;
FSRef ref ;
Boolean gotRef = CFURLGetFSRef ( URLToToggle , & ref ) ;
if ( gotRef ) {
status = GetIconRefFromFileInfo ( & ref ,
/ * fileNameLength * / 0 , / * fileName * / NULL ,
kFSCatInfoNone , / * catalogInfo * / NULL ,
kIconServicesNormalUsageFlag ,
& icon ,
/ * outLabel * / NULL ) ;
if ( status ! = noErr )
icon = NULL ;
}
2014-10-21 17:57:58 +02:00
LSSharedFileListInsertItemURL ( loginItems , kLSSharedFileListItemBeforeFirst , ( __bridge CFStringRef ) displayName , icon , URLToToggle , / * propertiesToSet * / NULL , / * propertiesToClear * / NULL ) ;
2012-08-20 21:34:54 +02:00
} else if ( ! enabled && ( existingItem ! = NULL ) )
LSSharedFileListItemRemove ( loginItems , existingItem ) ;
}
2014-03-27 12:38:43 -04:00
+ ( void ) checkRightStatus : ( OSStatus ) status
{
if ( status ! = errAuthorizationSuccess ) {
NSAlert * alert = [ NSAlert alertWithMessageText : @ "Authorization failed" defaultButton : @ "Quit" alternateButton : nil otherButton : nil informativeTextWithFormat : [ NSString stringWithFormat : @ "Authorization failed with code %d" , status ] ] ;
[ alert setAlertStyle : 2 ] ;
NSInteger result = [ alert runModal ] ;
if ( result = = NSAlertDefaultReturn ) {
[ [ NSApplication sharedApplication ] terminate : self ] ;
}
}
}
2012-08-20 21:34:54 +02:00
# pragma mark * * SMC - Binary Owner / Right Check * *
2013-12-21 09:26:27 -05:00
// TODO : It looks like this function is called inefficiently .
2012-08-20 21:34:54 +02:00
// call smc binary with sudo rights and apply
+ ( void ) setRights {
NSString * smcpath = [ [ NSBundle mainBundle ] pathForResource : @ "smc" ofType : @ "" ] ;
NSFileManager * fmanage = [ NSFileManager defaultManager ] ;
NSDictionary * fdic = [ fmanage attributesOfItemAtPath : smcpath error : nil ] ;
if ( [ [ fdic valueForKey : @ "NSFileOwnerAccountName" ] isEqualToString : @ "root" ] && [ [ fdic valueForKey : @ "NSFileGroupOwnerAccountName" ] isEqualToString : @ "admin" ] && ( [ [ fdic valueForKey : @ "NSFilePosixPermissions" ] intValue ] = = 3437 ) ) {
2013-12-21 09:26:27 -05:00
// If the SMC binary has already been modified to run as root , then do nothing .
return ;
}
// TODO : Is the usage of commPipe safe ?
2012-08-20 21:34:54 +02:00
FILE * commPipe ;
AuthorizationRef authorizationRef ;
AuthorizationItem gencitem = { "system.privilege.admin" , 0 , NULL , 0 } ;
AuthorizationRights gencright = { 1 , & gencitem } ;
int flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed ;
2013-12-21 09:26:27 -05:00
OSStatus status = AuthorizationCreate ( & gencright , kAuthorizationEmptyEnvironment , flags , & authorizationRef ) ;
2014-03-27 12:38:43 -04:00
[ self checkRightStatus : status ] ;
NSString * tool = @ "/usr/sbin/chown" ;
2014-10-21 17:57:58 +02:00
NSArray * argsArray = @ [ @ "root:admin" , smcpath ] ;
2012-08-20 21:34:54 +02:00
int i ;
char * args [ 255 ] ;
for ( i = 0 ; i < [ argsArray count ] ; i + + ) {
2014-10-21 17:57:58 +02:00
args [ i ] = ( char * ) [ argsArray [ i ] cString ] ;
2012-08-20 21:34:54 +02:00
}
args [ i ] = NULL ;
status = AuthorizationExecuteWithPrivileges ( authorizationRef , [ tool UTF8String ] , 0 , args , & commPipe ) ;
2014-03-27 12:38:43 -04:00
[ self checkRightStatus : status ] ;
// second call for suid - bit
2012-08-20 21:34:54 +02:00
tool = @ "/bin/chmod" ;
2014-10-21 17:57:58 +02:00
argsArray = @ [ @ "6555" , smcpath ] ;
2012-08-20 21:34:54 +02:00
for ( i = 0 ; i < [ argsArray count ] ; i + + ) {
2014-10-21 17:57:58 +02:00
args [ i ] = ( char * ) [ argsArray [ i ] cString ] ;
2012-08-20 21:34:54 +02:00
}
args [ i ] = NULL ;
status = AuthorizationExecuteWithPrivileges ( authorizationRef , [ tool UTF8String ] , 0 , args , & commPipe ) ;
2014-03-27 12:38:43 -04:00
[ self checkRightStatus : status ] ;
2012-08-20 21:34:54 +02:00
}
2016-10-12 03:48:56 +02:00
- ( void ) dealloc
{
[ [ NSDistributedNotificationCenter defaultCenter ] removeObserver : self ] ;
}
2012-08-20 21:34:54 +02:00
@ end
@ implementation NSNumber ( NumberAdditions )
- ( NSString * ) tohex {
return [ NSString stringWithFormat : @ "%0.4x" , [ self intValue ] < < 2 ] ;
}
- ( NSNumber * ) celsius_fahrenheit {
float celsius = [ self floatValue ] ;
float fahrenheit = ( celsius * 9 ) / 5 + 32 ;
2014-10-21 17:57:58 +02:00
return @ ( fahrenheit ) ;
2012-08-20 21:34:54 +02:00
}
@ end