borgend/dreamtime.py

changeset 94
2a11fd29c192
parent 89
51cc2e25af38
child 97
96d5adbe0205
equal deleted inserted replaced
93:040a0479f51e 94:2a11fd29c192
2 # Borgend by Tuomo Valkonen, 2018 2 # Borgend by Tuomo Valkonen, 2018
3 # 3 #
4 # This file implements system wake/sleep detection for scheduling adjustments. 4 # This file implements system wake/sleep detection for scheduling adjustments.
5 # 5 #
6 6
7 import Foundation
8 import AppKit
9 import platform 7 import platform
10 import time 8 import time
11 import threading 9 import threading
12 import weakref 10 import weakref
13 import datetime 11 import datetime
123 121
124 @staticmethod 122 @staticmethod
125 def _now(): 123 def _now():
126 return dreamtime() 124 return dreamtime()
127 125
128 # 126 if platform.system()=='Darwin':
129 # Wake up / sleep handling 127
130 # 128 import Foundation
131 129 import AppKit
132 class SleepHandler(Foundation.NSObject): 130
133 """ Handle wake/sleep notifications """ 131 #
134 132 # Wake up / sleep handling
135 def init(self): 133 #
136 self.__sleeptime=None 134
137 self.__slept=0 135 class SleepHandler(Foundation.NSObject):
138 self.__epoch=time.monotonic() 136 """ Handle wake/sleep notifications """
139 self.__lock=threading.Lock() 137
140 self.__callbacks=weakref.WeakKeyDictionary() 138 def init(self):
141 139 self.__sleeptime=None
142 return self 140 self.__slept=0
143 141 self.__epoch=time.monotonic()
144 def handleSleepNotification_(self, aNotification): 142 self.__lock=threading.Lock()
145 logger.info("System going to sleep") 143 self.__callbacks=weakref.WeakKeyDictionary()
146 now=time.monotonic() 144
147 with self.__lock: 145 return self
148 self.__sleeptime=now 146
149 147 def handleSleepNotification_(self, aNotification):
150 def handleWakeNotification_(self, aNotification): 148 logger.info("System going to sleep")
151 logger.info("System waking up from sleep")
152 try:
153 now=time.monotonic() 149 now=time.monotonic()
154 with self.__lock: 150 with self.__lock:
155 if self.__sleeptime: 151 self.__sleeptime=now
156 slept=max(0, now-self.__sleeptime) 152
157 logger.info("Slept %f seconds" % slept) 153 def handleWakeNotification_(self, aNotification):
158 self.__slept=self.__slept+slept 154 logger.info("System waking up from sleep")
159 self.__sleeptime=None
160 callbacks=self.__callbacks.copy()
161 except:
162 logger.exception("Bug in wakeup handler")
163
164 for callback in callbacks.values():
165 try: 155 try:
166 callback() 156 now=time.monotonic()
167 except Exception: 157 with self.__lock:
168 logger.exception("Error in wake notification callback") 158 if self.__sleeptime:
169 159 slept=max(0, now-self.__sleeptime)
170 # Return difference to time.monotonic() 160 logger.info("Slept %f seconds" % slept)
171 def diff(self): 161 self.__slept=self.__slept+slept
172 with self.__lock: 162 self.__sleeptime=None
173 diff=self.__epoch+self.__slept 163 callbacks=self.__callbacks.copy()
174 return diff 164 except:
175 165 logger.exception("Bug in wakeup handler")
176 # Weirdo (Py)ObjC naming to stop it form choking up 166
177 def addForObj_aCallback_(self, obj, callback): 167 for callback in callbacks.values():
178 with self.__lock: 168 try:
179 self.__callbacks[obj]=callback 169 callback()
180 170 except Exception:
181 # obj is to use a a key in a weak key dictionary 171 logger.exception("Error in wake notification callback")
182 def add_callback(obj, callback): 172
183 global _dreamtime_monitor 173 # Return difference to time.monotonic()
184 174 def diff(self):
185 monitor=_dreamtime_monitor 175 with self.__lock:
186 if not monitor: 176 diff=self.__epoch+self.__slept
187 raise Exception("Dreamtime monitor not started") 177 return diff
188 else: 178
189 monitor.addForObj_aCallback_(obj, callback) 179 # Weirdo (Py)ObjC naming to stop it form choking up
190 180 def addForObj_aCallback_(self, obj, callback):
191 def start_monitoring(): 181 with self.__lock:
192 global _dreamtime_monitor 182 self.__callbacks[obj]=callback
193 183
194 if platform.system()=='Darwin': 184 # obj is to use a a key in a weak key dictionary
185 def add_callback(obj, callback):
186 global _dreamtime_monitor
187
188 monitor=_dreamtime_monitor
189 if not monitor:
190 raise Exception("Dreamtime monitor not started")
191 else:
192 monitor.addForObj_aCallback_(obj, callback)
193
194 def start_monitoring():
195 global _dreamtime_monitor
196
195 logger.debug("Starting to monitor system sleep") 197 logger.debug("Starting to monitor system sleep")
196 workspace = AppKit.NSWorkspace.sharedWorkspace() 198 workspace = AppKit.NSWorkspace.sharedWorkspace()
197 notification_center = workspace.notificationCenter() 199 notification_center = workspace.notificationCenter()
198 _dreamtime_monitor = SleepHandler.new() 200 _dreamtime_monitor = SleepHandler.new()
199 201
206 notification_center.addObserver_selector_name_object_( 208 notification_center.addObserver_selector_name_object_(
207 _dreamtime_monitor, 209 _dreamtime_monitor,
208 "handleWakeNotification:", 210 "handleWakeNotification:",
209 AppKit.NSWorkspaceDidWakeNotification, 211 AppKit.NSWorkspaceDidWakeNotification,
210 None) 212 None)
211 else: 213
214 else: # Not on macOS
215
216 def add_callback(obj, callback):
217 pass
218
219 def start_monitoring():
212 logger.warning(("No system sleep monitor implemented for '%s'" 220 logger.warning(("No system sleep monitor implemented for '%s'"
213 % platform.system())) 221 % platform.system()))
214 222

mercurial