mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
feat: Introduce PowerManager on macOS (#7543)
- Use modern APIs to prevent idle system sleep. - Consolidate all related logic. - Make Controller class a little bit less huge. Signed-off-by: Dzmitry Neviadomski <nevack.d@gmail.com>
This commit is contained in:
committed by
GitHub
parent
90b52bc65c
commit
85a325ed71
@@ -46,7 +46,6 @@
|
||||
4D36BA780CA2F00800A63CA5 /* peer-mgr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D36BA690CA2F00800A63CA5 /* peer-mgr.h */; };
|
||||
4D36BA790CA2F00800A63CA5 /* peer-msgs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D36BA6A0CA2F00800A63CA5 /* peer-msgs.cc */; };
|
||||
4D36BA7A0CA2F00800A63CA5 /* peer-msgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D36BA6B0CA2F00800A63CA5 /* peer-msgs.h */; };
|
||||
4D3EA0AA08AE13C600EA10C2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D3EA0A908AE13C600EA10C2 /* IOKit.framework */; };
|
||||
4D4ADFC70DA1631500A68297 /* blocklist.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2D3078E0D9EC45F0051FD27 /* blocklist.cc */; };
|
||||
4D8017EA10BBC073008A4AF2 /* torrent-magnet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D8017E810BBC073008A4AF2 /* torrent-magnet.cc */; };
|
||||
4D8017EB10BBC073008A4AF2 /* torrent-magnet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D8017E910BBC073008A4AF2 /* torrent-magnet.h */; };
|
||||
@@ -481,6 +480,7 @@
|
||||
EDBAAC8C29E486BC00D9495F /* ip-cache.h in Headers */ = {isa = PBXBuildFile; fileRef = EDBAAC8B29E486BC00D9495F /* ip-cache.h */; };
|
||||
EDBAAC8E29E486C200D9495F /* ip-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDBAAC8D29E486C200D9495F /* ip-cache.cc */; };
|
||||
EDBDFA9E25AFCCA60093D9C1 /* evutil_time.c in Sources */ = {isa = PBXBuildFile; fileRef = EDBDFA9D25AFCCA60093D9C1 /* evutil_time.c */; };
|
||||
EDC749F92D98AE3000A12D0F /* PowerManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDC749F82D98AE2900A12D0F /* PowerManager.mm */; };
|
||||
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A044CBD8C049AFCBD4DB411 /* block-info.h */; settings = {ATTRIBUTES = (Project, ); }; };
|
||||
F63480631E1D7274005B9E09 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F63480621E1D7274005B9E09 /* Images.xcassets */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -828,7 +828,6 @@
|
||||
4D36BA690CA2F00800A63CA5 /* peer-mgr.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "peer-mgr.h"; sourceTree = "<group>"; };
|
||||
4D36BA6A0CA2F00800A63CA5 /* peer-msgs.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-msgs.cc"; sourceTree = "<group>"; };
|
||||
4D36BA6B0CA2F00800A63CA5 /* peer-msgs.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "peer-msgs.h"; sourceTree = "<group>"; };
|
||||
4D3EA0A908AE13C600EA10C2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
||||
4D8017E810BBC073008A4AF2 /* torrent-magnet.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "torrent-magnet.cc"; sourceTree = "<group>"; };
|
||||
4D8017E910BBC073008A4AF2 /* torrent-magnet.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "torrent-magnet.h"; sourceTree = "<group>"; };
|
||||
4D80185710BBC0B0008A4AF2 /* magnet-metainfo.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "magnet-metainfo.cc"; sourceTree = "<group>"; };
|
||||
@@ -1474,6 +1473,8 @@
|
||||
EDBAAC8B29E486BC00D9495F /* ip-cache.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = "ip-cache.h"; sourceTree = "<group>"; };
|
||||
EDBAAC8D29E486C200D9495F /* ip-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "ip-cache.cc"; sourceTree = "<group>"; };
|
||||
EDBDFA9D25AFCCA60093D9C1 /* evutil_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = evutil_time.c; sourceTree = "<group>"; };
|
||||
EDC749F72D98ADE200A12D0F /* PowerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PowerManager.h; sourceTree = "<group>"; };
|
||||
EDC749F82D98AE2900A12D0F /* PowerManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PowerManager.mm; sourceTree = "<group>"; };
|
||||
F63480621E1D7274005B9E09 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -1503,7 +1504,6 @@
|
||||
files = (
|
||||
C87369652809984200573C90 /* UserNotifications.framework in Frameworks */,
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||
4D3EA0AA08AE13C600EA10C2 /* IOKit.framework in Frameworks */,
|
||||
4D1838DD09DEC0E80047D688 /* libtransmission.a in Frameworks */,
|
||||
A24F19080A3A790800C9C145 /* Sparkle.framework in Frameworks */,
|
||||
C88771B52803EEB1005C7523 /* libiconv.tbd in Frameworks */,
|
||||
@@ -1789,6 +1789,8 @@
|
||||
A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */,
|
||||
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */,
|
||||
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */,
|
||||
EDC749F72D98ADE200A12D0F /* PowerManager.h */,
|
||||
EDC749F82D98AE2900A12D0F /* PowerManager.mm */,
|
||||
ED9862952B979AA2002F3035 /* Utils.h */,
|
||||
ED9862962B979AA2002F3035 /* Utils.mm */,
|
||||
A2AB883916A399A6008FAD50 /* VDKQueue */,
|
||||
@@ -1898,7 +1900,6 @@
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
|
||||
29B97324FDCFA39411CA2CEA /* AppKit.framework */,
|
||||
29B97325FDCFA39411CA2CEA /* Foundation.framework */,
|
||||
4D3EA0A908AE13C600EA10C2 /* IOKit.framework */,
|
||||
A2E669780F5B8E5A00B4251A /* Security.framework */,
|
||||
A22CFB810FB66EF30009BD3E /* Carbon.framework */,
|
||||
A221DCC7104B3660008A642D /* Quartz.framework */,
|
||||
@@ -3556,6 +3557,7 @@
|
||||
A2ED7D8F0CEF431B00970975 /* FilterButton.mm in Sources */,
|
||||
45A7D32C2843B55F00F0C32A /* PriorityPopUpButtonCell.mm in Sources */,
|
||||
A25892640CF1F7E800CCCDDF /* StatsWindowController.mm in Sources */,
|
||||
EDC749F92D98AE3000A12D0F /* PowerManager.mm in Sources */,
|
||||
A2C89D600CFCBF57004CC2BC /* ButtonToolbarItem.mm in Sources */,
|
||||
A219798B0D07B78400438EA7 /* GroupToolbarItem.mm in Sources */,
|
||||
4521532B29AF891F009331B0 /* GroupCell.mm in Sources */,
|
||||
|
||||
@@ -143,6 +143,8 @@ target_sources(${TR_NAME}-mac
|
||||
PiecesView.mm
|
||||
PortChecker.h
|
||||
PortChecker.mm
|
||||
PowerManager.h
|
||||
PowerManager.mm
|
||||
PredicateEditorRowTemplateAny.h
|
||||
PredicateEditorRowTemplateAny.mm
|
||||
PrefsController.h
|
||||
@@ -412,7 +414,6 @@ target_link_libraries(${TR_NAME}-mac
|
||||
"-framework AppKit"
|
||||
"-framework Carbon"
|
||||
"-framework Foundation"
|
||||
"-framework IOKit"
|
||||
"-framework Quartz"
|
||||
"-framework Security"
|
||||
"-weak_framework UserNotifications")
|
||||
|
||||
@@ -143,8 +143,6 @@ typedef NS_ENUM(NSUInteger, AddType) { //
|
||||
|
||||
- (void)beginCreateFile:(NSNotification*)notification;
|
||||
|
||||
- (void)sleepCallback:(natural_t)messageType argument:(void*)messageArgument;
|
||||
|
||||
@property(nonatomic, readonly) VDKQueue* fileWatcherQueue;
|
||||
|
||||
- (void)torrentTableViewSelectionDidChange:(NSNotification*)notification;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
@import IOKit;
|
||||
@import IOKit.pwr_mgt;
|
||||
@import Carbon;
|
||||
@import UserNotifications;
|
||||
|
||||
@@ -56,6 +54,7 @@
|
||||
#import "ExpandedPathToPathTransformer.h"
|
||||
#import "ExpandedPathToIconTransformer.h"
|
||||
#import "VersionComparator.h"
|
||||
#import "PowerManager.h"
|
||||
|
||||
typedef NSString* ToolbarItemIdentifier NS_TYPED_EXTENSIBLE_ENUM;
|
||||
|
||||
@@ -176,11 +175,6 @@ static tr_rpc_callback_status rpcCallback([[maybe_unused]] tr_session* handle, t
|
||||
return TR_RPC_NOREMOVE; //we'll do the remove manually
|
||||
}
|
||||
|
||||
static void sleepCallback(void* controller, io_service_t /*y*/, natural_t messageType, void* messageArgument)
|
||||
{
|
||||
[(__bridge Controller*)controller sleepCallback:messageType argument:messageArgument];
|
||||
}
|
||||
|
||||
// 2.90 was infected with ransomware which we now check for and attempt to remove
|
||||
static void removeKeRangerRansomware()
|
||||
{
|
||||
@@ -271,7 +265,7 @@ static void removeKeRangerRansomware()
|
||||
NSLog(@"OSX.KeRanger.A ransomware removal completed, proceeding to normal operation");
|
||||
}
|
||||
|
||||
@interface Controller ()<UNUserNotificationCenterDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
|
||||
@interface Controller ()<UNUserNotificationCenterDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, PowerManagerDelegate>
|
||||
|
||||
@property(nonatomic) IBOutlet NSWindow* fWindow;
|
||||
@property(nonatomic) IBOutlet NSStackView* fStackView;
|
||||
@@ -311,7 +305,6 @@ static void removeKeRangerRansomware()
|
||||
|
||||
@property(nonatomic) DragOverlayWindow* fOverlayWindow;
|
||||
|
||||
@property(nonatomic) io_connect_t fRootPort;
|
||||
@property(nonatomic) NSTimer* fTimer;
|
||||
|
||||
@property(nonatomic) StatusBarController* fStatusBar;
|
||||
@@ -338,7 +331,6 @@ static void removeKeRangerRansomware()
|
||||
@property(nonatomic) BOOL fGlobalPopoverShown;
|
||||
@property(nonatomic) NSView* fPositioningView;
|
||||
@property(nonatomic) BOOL fSoundPlaying;
|
||||
@property(nonatomic) id fNoNapActivity;
|
||||
|
||||
@end
|
||||
|
||||
@@ -702,18 +694,6 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
//this must be called after showStatusBar:
|
||||
[self.fStatusBar updateWithDownload:0.0 upload:0.0];
|
||||
|
||||
//register for sleep notifications
|
||||
IONotificationPortRef notify;
|
||||
io_object_t iterator;
|
||||
if ((self.fRootPort = IORegisterForSystemPower((__bridge void*)(self), ¬ify, sleepCallback, &iterator)))
|
||||
{
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopCommonModes);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Could not IORegisterForSystemPower");
|
||||
}
|
||||
|
||||
auto* const session = self.fLib;
|
||||
|
||||
//load previous transfers
|
||||
@@ -889,8 +869,8 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
|
||||
NSApp.servicesProvider = self;
|
||||
|
||||
self.fNoNapActivity = [NSProcessInfo.processInfo beginActivityWithOptions:NSActivityUserInitiatedAllowingIdleSystemSleep
|
||||
reason:@"No napping on the job!"];
|
||||
[PowerManager.shared setDelegate:self];
|
||||
[PowerManager.shared start];
|
||||
|
||||
//register for dock icon drags (has to be in applicationDidFinishLaunching: to work)
|
||||
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleOpenContentsEvent:replyEvent:)
|
||||
@@ -1038,7 +1018,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
{
|
||||
self.fQuitting = YES;
|
||||
|
||||
[NSProcessInfo.processInfo endActivity:self.fNoNapActivity];
|
||||
[PowerManager.shared stop];
|
||||
|
||||
//stop the Bonjour service
|
||||
if (BonjourController.defaultControllerExists)
|
||||
@@ -2378,6 +2358,8 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
{
|
||||
CGFloat dlRate = 0.0, ulRate = 0.0;
|
||||
BOOL anyCompleted = NO;
|
||||
BOOL anyActive = NO;
|
||||
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[torrent update];
|
||||
@@ -2387,8 +2369,11 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
ulRate += torrent.uploadRate;
|
||||
|
||||
anyCompleted |= torrent.finishedSeeding;
|
||||
anyActive |= torrent.active && !torrent.stalled && !torrent.error;
|
||||
}
|
||||
|
||||
PowerManager.shared.shouldPreventSleep = anyActive && [self.fDefaults boolForKey:@"SleepPrevent"];
|
||||
|
||||
if (!NSApp.hidden)
|
||||
{
|
||||
if (self.fWindow.visible)
|
||||
@@ -5007,11 +4992,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)sleepCallback:(natural_t)messageType argument:(void*)messageArgument
|
||||
{
|
||||
switch (messageType)
|
||||
{
|
||||
case kIOMessageSystemWillSleep:
|
||||
- (void)systemWillSleep
|
||||
{
|
||||
//stop all transfers (since some are active) before going to sleep and remember to resume when we wake up
|
||||
BOOL anyActive = NO;
|
||||
@@ -5029,36 +5010,15 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
{
|
||||
sleep(15);
|
||||
}
|
||||
|
||||
IOAllowPowerChange(self.fRootPort, (long)messageArgument);
|
||||
break;
|
||||
}
|
||||
|
||||
case kIOMessageCanSystemSleep:
|
||||
if ([self.fDefaults boolForKey:@"SleepPrevent"])
|
||||
- (void)systemDidWakeUp
|
||||
{
|
||||
//prevent idle sleep unless no torrents are active
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
if (torrent.active && !torrent.stalled && !torrent.error)
|
||||
{
|
||||
IOCancelPowerChange(self.fRootPort, (long)messageArgument);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IOAllowPowerChange(self.fRootPort, (long)messageArgument);
|
||||
break;
|
||||
|
||||
case kIOMessageSystemHasPoweredOn:
|
||||
//resume sleeping transfers after we wake up
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[torrent wakeUp];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSMenu*)applicationDockMenu:(NSApplication*)sender
|
||||
|
||||
26
macosx/PowerManager.h
Normal file
26
macosx/PowerManager.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// This file Copyright © Transmission authors and contributors.
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@protocol PowerManagerDelegate<NSObject>
|
||||
|
||||
- (void)systemWillSleep;
|
||||
- (void)systemDidWakeUp;
|
||||
|
||||
@end
|
||||
|
||||
@interface PowerManager : NSObject
|
||||
|
||||
@property(nonatomic, class, readonly) PowerManager* shared;
|
||||
|
||||
@property(nonatomic, weak) id<PowerManagerDelegate> delegate;
|
||||
@property(nonatomic) BOOL shouldPreventSleep;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (void)start;
|
||||
- (void)stop;
|
||||
|
||||
@end
|
||||
172
macosx/PowerManager.mm
Normal file
172
macosx/PowerManager.mm
Normal file
@@ -0,0 +1,172 @@
|
||||
// This file Copyright © Transmission authors and contributors.
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#import "PowerManager.h"
|
||||
|
||||
#include <os/log.h>
|
||||
|
||||
@interface PowerManager ()
|
||||
|
||||
@property(nonatomic, readonly) os_log_t log;
|
||||
@property(getter=isListening) BOOL listening;
|
||||
|
||||
@property(nonatomic) id<NSObject> noNapActivity;
|
||||
@property(nonatomic) id<NSObject> noSleepActivity;
|
||||
|
||||
- (void)systemWillSleep:(NSNotification*)notification;
|
||||
- (void)systemDidWakeUp:(NSNotification*)notification;
|
||||
|
||||
- (void)powerStateDidChange:(NSNotification*)notification NS_AVAILABLE_MAC(12_0);
|
||||
|
||||
@end
|
||||
|
||||
@implementation PowerManager
|
||||
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static PowerManager* sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[PowerManager alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_log = os_log_create("org.transmission", "power");
|
||||
_listening = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stop];
|
||||
}
|
||||
|
||||
- (void)start
|
||||
{
|
||||
os_log_info(self.log, "Starting power manager");
|
||||
if (!self.isListening)
|
||||
{
|
||||
os_log_debug(self.log, "Registering sleep/wake/low power mode notifications");
|
||||
[NSWorkspace.sharedWorkspace.notificationCenter addObserver:self selector:@selector(systemWillSleep:)
|
||||
name:NSWorkspaceWillSleepNotification
|
||||
object:nil];
|
||||
[NSWorkspace.sharedWorkspace.notificationCenter addObserver:self selector:@selector(systemDidWakeUp:)
|
||||
name:NSWorkspaceDidWakeNotification
|
||||
object:nil];
|
||||
if (@available(macOS 12.0, *))
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(powerStateDidChange:)
|
||||
name:NSProcessInfoPowerStateDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
self.listening = YES;
|
||||
}
|
||||
|
||||
if (self.noNapActivity == nil)
|
||||
{
|
||||
os_log_debug(self.log, "Starting no-nap activity");
|
||||
self.noNapActivity = [NSProcessInfo.processInfo beginActivityWithOptions:NSActivityUserInitiatedAllowingIdleSystemSleep
|
||||
reason:@"Transmission: Application is active"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stop
|
||||
{
|
||||
os_log_info(self.log, "Stopping power manager");
|
||||
if (self.isListening)
|
||||
{
|
||||
os_log_debug(self.log, "Unregistering sleep/wake/low power mode notifications");
|
||||
[NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self name:NSWorkspaceWillSleepNotification object:nil];
|
||||
[NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self name:NSWorkspaceDidWakeNotification object:nil];
|
||||
if (@available(macOS 12.0, *))
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self name:NSProcessInfoPowerStateDidChangeNotification object:nil];
|
||||
}
|
||||
self.listening = NO;
|
||||
}
|
||||
|
||||
if (self.noNapActivity != nil)
|
||||
{
|
||||
os_log_debug(self.log, "Ending no-nap activity");
|
||||
[NSProcessInfo.processInfo endActivity:self.noNapActivity];
|
||||
self.noNapActivity = nil;
|
||||
}
|
||||
|
||||
if (self.noSleepActivity != nil)
|
||||
{
|
||||
os_log_debug(self.log, "Ending no-sleep activity");
|
||||
[NSProcessInfo.processInfo endActivity:self.noSleepActivity];
|
||||
self.noSleepActivity = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)systemWillSleep:(NSNotification*)notification
|
||||
{
|
||||
os_log_info(self.log, "System will sleep notification received");
|
||||
[self.delegate systemWillSleep];
|
||||
}
|
||||
|
||||
- (void)systemDidWakeUp:(NSNotification*)notification
|
||||
{
|
||||
os_log_info(self.log, "System did wake up notification received");
|
||||
[self.delegate systemDidWakeUp];
|
||||
}
|
||||
|
||||
- (void)powerStateDidChange:(NSNotification*)notification
|
||||
{
|
||||
os_log_info(self.log, "Power state did change notification received");
|
||||
if (NSProcessInfo.processInfo.lowPowerModeEnabled)
|
||||
{
|
||||
os_log_info(self.log, "Low power mode enabled, disabling sleep prevention");
|
||||
self.shouldPreventSleep = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setShouldPreventSleep:(BOOL)shouldPreventSleep
|
||||
{
|
||||
if (@available(macOS 12.0, *))
|
||||
{
|
||||
if (shouldPreventSleep && NSProcessInfo.processInfo.lowPowerModeEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldPreventSleep)
|
||||
{
|
||||
if (self.noSleepActivity != nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
os_log_info(self.log, "Starting no-sleep activity");
|
||||
self.noSleepActivity = [NSProcessInfo.processInfo beginActivityWithOptions:NSActivityIdleSystemSleepDisabled
|
||||
reason:@"Transmission: Active Torrents"];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.noSleepActivity == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
os_log_info(self.log, "Ending no-sleep activity");
|
||||
[NSProcessInfo.processInfo endActivity:self.noSleepActivity];
|
||||
self.noSleepActivity = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldPreventSleep
|
||||
{
|
||||
return self.noSleepActivity != nil;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user