|
@@ -1,16 +1,16 @@
|
|
|
-#-----------------------------------------------------------------------------
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
# Copyright (C) 2013 Min RK
|
|
|
#
|
|
|
# Distributed under the terms of the 2-clause BSD License.
|
|
|
-#-----------------------------------------------------------------------------
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
|
|
|
from contextlib import contextmanager
|
|
|
|
|
|
import ctypes
|
|
|
import ctypes.util
|
|
|
|
|
|
-objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
|
|
|
-_ = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Foundation'))
|
|
|
+objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc"))
|
|
|
+_ = ctypes.cdll.LoadLibrary(ctypes.util.find_library("Foundation"))
|
|
|
|
|
|
void_p = ctypes.c_void_p
|
|
|
ull = ctypes.c_uint64
|
|
@@ -22,74 +22,82 @@ objc.objc_msgSend.argtypes = [void_p, void_p]
|
|
|
|
|
|
msg = objc.objc_msgSend
|
|
|
|
|
|
+
|
|
|
def _utf8(s):
|
|
|
"""ensure utf8 bytes"""
|
|
|
if not isinstance(s, bytes):
|
|
|
- s = s.encode('utf8')
|
|
|
+ s = s.encode("utf8")
|
|
|
return s
|
|
|
|
|
|
+
|
|
|
def n(name):
|
|
|
"""create a selector name (for methods)"""
|
|
|
return objc.sel_registerName(_utf8(name))
|
|
|
|
|
|
+
|
|
|
def C(classname):
|
|
|
"""get an ObjC Class by name"""
|
|
|
ret = objc.objc_getClass(_utf8(classname))
|
|
|
assert ret is not None, "Couldn't find Class %s" % classname
|
|
|
return ret
|
|
|
|
|
|
+
|
|
|
# constants from Foundation
|
|
|
|
|
|
-NSActivityIdleDisplaySleepDisabled = (1 << 40)
|
|
|
-NSActivityIdleSystemSleepDisabled = (1 << 20)
|
|
|
-NSActivitySuddenTerminationDisabled = (1 << 14)
|
|
|
-NSActivityAutomaticTerminationDisabled = (1 << 15)
|
|
|
-NSActivityUserInitiated = (0x00FFFFFF | NSActivityIdleSystemSleepDisabled)
|
|
|
-NSActivityUserInitiatedAllowingIdleSystemSleep = (NSActivityUserInitiated & ~NSActivityIdleSystemSleepDisabled)
|
|
|
-NSActivityBackground = 0x000000FF
|
|
|
-NSActivityLatencyCritical = 0xFF00000000
|
|
|
+NSActivityIdleDisplaySleepDisabled = 1 << 40
|
|
|
+NSActivityIdleSystemSleepDisabled = 1 << 20
|
|
|
+NSActivitySuddenTerminationDisabled = 1 << 14
|
|
|
+NSActivityAutomaticTerminationDisabled = 1 << 15
|
|
|
+NSActivityUserInitiated = 0x00FFFFFF | NSActivityIdleSystemSleepDisabled
|
|
|
+NSActivityUserInitiatedAllowingIdleSystemSleep = (
|
|
|
+ NSActivityUserInitiated & ~NSActivityIdleSystemSleepDisabled
|
|
|
+)
|
|
|
+NSActivityBackground = 0x000000FF
|
|
|
+NSActivityLatencyCritical = 0xFF00000000
|
|
|
+
|
|
|
|
|
|
def beginActivityWithOptions(options, reason=""):
|
|
|
"""Wrapper for:
|
|
|
-
|
|
|
- [ [ NSProcessInfo processInfo]
|
|
|
+
|
|
|
+ [ [ NSProcessInfo processInfo]
|
|
|
beginActivityWithOptions: (uint64)options
|
|
|
reason: (str)reason
|
|
|
]
|
|
|
"""
|
|
|
- NSProcessInfo = C('NSProcessInfo')
|
|
|
- NSString = C('NSString')
|
|
|
-
|
|
|
+ NSProcessInfo = C("NSProcessInfo")
|
|
|
+ NSString = C("NSString")
|
|
|
+
|
|
|
objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
|
|
|
reason = msg(NSString, n("stringWithUTF8String:"), _utf8(reason))
|
|
|
objc.objc_msgSend.argtypes = [void_p, void_p]
|
|
|
- info = msg(NSProcessInfo, n('processInfo'))
|
|
|
+ info = msg(NSProcessInfo, n("processInfo"))
|
|
|
objc.objc_msgSend.argtypes = [void_p, void_p, ull, void_p]
|
|
|
- activity = msg(info,
|
|
|
- n('beginActivityWithOptions:reason:'),
|
|
|
- ull(options),
|
|
|
- void_p(reason)
|
|
|
+ activity = msg(
|
|
|
+ info, n("beginActivityWithOptions:reason:"), ull(options), void_p(reason)
|
|
|
)
|
|
|
return activity
|
|
|
|
|
|
+
|
|
|
def endActivity(activity):
|
|
|
"""end a process activity assertion"""
|
|
|
- NSProcessInfo = C('NSProcessInfo')
|
|
|
+ NSProcessInfo = C("NSProcessInfo")
|
|
|
objc.objc_msgSend.argtypes = [void_p, void_p]
|
|
|
- info = msg(NSProcessInfo, n('processInfo'))
|
|
|
+ info = msg(NSProcessInfo, n("processInfo"))
|
|
|
objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
|
|
|
msg(info, n("endActivity:"), void_p(activity))
|
|
|
|
|
|
+
|
|
|
_theactivity = None
|
|
|
|
|
|
+
|
|
|
def nope():
|
|
|
"""disable App Nap by setting NSActivityUserInitiatedAllowingIdleSystemSleep"""
|
|
|
global _theactivity
|
|
|
_theactivity = beginActivityWithOptions(
|
|
|
- NSActivityUserInitiatedAllowingIdleSystemSleep,
|
|
|
- "Because Reasons"
|
|
|
+ NSActivityUserInitiatedAllowingIdleSystemSleep, "Because Reasons"
|
|
|
)
|
|
|
|
|
|
+
|
|
|
def nap():
|
|
|
"""end the caffeinated state started by `nope`"""
|
|
|
global _theactivity
|
|
@@ -97,17 +105,18 @@ def nap():
|
|
|
endActivity(_theactivity)
|
|
|
_theactivity = None
|
|
|
|
|
|
+
|
|
|
def napping_allowed():
|
|
|
"""is napping allowed?"""
|
|
|
return _theactivity is None
|
|
|
|
|
|
+
|
|
|
@contextmanager
|
|
|
def nope_scope(
|
|
|
- options=NSActivityUserInitiatedAllowingIdleSystemSleep,
|
|
|
- reason="Because Reasons"
|
|
|
- ):
|
|
|
+ options=NSActivityUserInitiatedAllowingIdleSystemSleep, reason="Because Reasons"
|
|
|
+):
|
|
|
"""context manager for beginActivityWithOptions.
|
|
|
-
|
|
|
+
|
|
|
Within this context, App Nap will be disabled.
|
|
|
"""
|
|
|
activity = beginActivityWithOptions(options, reason)
|
|
@@ -116,6 +125,7 @@ def nope_scope(
|
|
|
finally:
|
|
|
endActivity(activity)
|
|
|
|
|
|
+
|
|
|
__all__ = [
|
|
|
"NSActivityIdleDisplaySleepDisabled",
|
|
|
"NSActivityIdleSystemSleepDisabled",
|