| 5 import Foundation |
5 import Foundation |
| 6 import AppKit |
6 import AppKit |
| 7 import platform |
7 import platform |
| 8 import time |
8 import time |
| 9 import threading |
9 import threading |
| 10 import borgend |
|
| 11 import weakref |
10 import weakref |
| 12 import datetime |
11 import datetime |
| |
12 import borgend |
| 13 |
13 |
| 14 logger=borgend.logger.getChild(__name__) |
14 logger=borgend.logger.getChild(__name__) |
| 15 |
15 |
| 16 _dreamtime_monitor=[None] |
16 _dreamtime_monitor=None |
| 17 |
17 |
| 18 # |
18 # |
| 19 # Support classes for dealing with different times |
19 # Support classes for dealing with different times |
| 20 # |
20 # |
| 21 |
21 |
| 22 def dreamtime(): |
22 # Return difference (delay) of "dreamtime" to monotonic time |
| 23 if _dreamtime_monitor[0]: |
23 def dreamtime_difference(): |
| 24 return max(0, time.monotonic()-_dreamtime_monitor[0].diff()) |
24 if _dreamtime_monitor: |
| |
25 return _dreamtime_monitor.diff() |
| 25 else: |
26 else: |
| 26 return time.monotonic() |
27 return time.monotonic() |
| |
28 |
| |
29 # Return "dreamtime" |
| |
30 def dreamtime(): |
| |
31 return max(0, time.monotonic()-dreamtime_difference()) |
| 27 |
32 |
| 28 class Time: |
33 class Time: |
| 29 def realtime(self): |
34 def realtime(self): |
| 30 raise NotImplementedError |
35 raise NotImplementedError |
| 31 |
36 |
| 124 |
132 |
| 125 def init(self): |
133 def init(self): |
| 126 self.__sleeptime=None |
134 self.__sleeptime=None |
| 127 self.__slept=0 |
135 self.__slept=0 |
| 128 self.__epoch=time.monotonic() |
136 self.__epoch=time.monotonic() |
| 129 self._lock=threading.Lock() |
137 self.__lock=threading.Lock() |
| 130 self._callbacks=weakref.WeakKeyDictionary() |
138 self.__callbacks=weakref.WeakKeyDictionary() |
| 131 |
139 |
| 132 return self |
140 return self |
| 133 |
141 |
| 134 def handleSleepNotification_(self, aNotification): |
142 def handleSleepNotification_(self, aNotification): |
| 135 logger.info("System going to sleep") |
143 logger.info("System going to sleep") |
| 136 now=time.monotonic() |
144 now=time.monotonic() |
| 137 with self._lock: |
145 with self.__lock: |
| 138 self.__sleeptime=now |
146 self.__sleeptime=now |
| 139 |
147 |
| 140 def handleWakeNotification_(self, aNotification): |
148 def handleWakeNotification_(self, aNotification): |
| 141 logger.info("System waking up from sleep") |
149 logger.info("System waking up from sleep") |
| 142 try: |
150 try: |
| 143 now=time.monotonic() |
151 now=time.monotonic() |
| 144 with self._lock: |
152 with self.__lock: |
| 145 if self.__sleeptime: |
153 if self.__sleeptime: |
| 146 slept=max(0, now-self.__sleeptime) |
154 slept=max(0, now-self.__sleeptime) |
| 147 logger.info("Slept %f seconds" % slept) |
155 logger.info("Slept %f seconds" % slept) |
| 148 self.__slept=self.__slept+slept |
156 self.__slept=self.__slept+slept |
| 149 self.__sleeptime=None |
157 self.__sleeptime=None |
| 150 callbacks=self._callbacks.copy() |
158 callbacks=self.__callbacks.copy() |
| 151 except: |
159 except: |
| 152 logger.exception("Bug in wakeup handler") |
160 logger.exception("Bug in wakeup handler") |
| 153 |
161 |
| 154 for callback in callbacks.values(): |
162 for callback in callbacks.values(): |
| 155 try: |
163 try: |
| 157 except Exception: |
165 except Exception: |
| 158 logger.exception("Error in wake notification callback") |
166 logger.exception("Error in wake notification callback") |
| 159 |
167 |
| 160 # Return difference to time.monotonic() |
168 # Return difference to time.monotonic() |
| 161 def diff(self): |
169 def diff(self): |
| 162 with self._lock: |
170 with self.__lock: |
| 163 diff=self.__epoch+self.__slept |
171 diff=self.__epoch+self.__slept |
| 164 return diff |
172 return diff |
| 165 |
173 |
| 166 # Obj-C hates this |
174 # Weirdo (Py)ObjC naming to stop it form choking up |
| 167 # def add_callback(self, obj, callback): |
175 def addForObj_aCallback_(self, obj, callback): |
| 168 # with self.lock: |
176 with self.__lock: |
| 169 # self.__callbacks[obj]=callback |
177 self.__callbacks[obj]=callback |
| 170 |
178 |
| 171 # obj is to use a a key in a weak key dictionary |
179 # obj is to use a a key in a weak key dictionary |
| 172 def add_callback(obj, callback): |
180 def add_callback(obj, callback): |
| 173 monitor=_dreamtime_monitor[0] |
181 global _dreamtime_monitor |
| |
182 |
| |
183 monitor=_dreamtime_monitor |
| 174 if not monitor: |
184 if not monitor: |
| 175 raise Exception("Dreamtime monitor not started") |
185 raise Exception("Dreamtime monitor not started") |
| 176 else: |
186 else: |
| 177 #monitor.add_my_callback(obj, callback) |
187 monitor.addForObj_aCallback_(obj, callback) |
| 178 with monitor._lock: |
|
| 179 monitor._callbacks[obj]=callback |
|
| 180 |
188 |
| 181 def start_monitoring(): |
189 def start_monitoring(): |
| |
190 global _dreamtime_monitor |
| |
191 |
| 182 if platform.system()=='Darwin': |
192 if platform.system()=='Darwin': |
| 183 logger.debug("Starting to monitor system sleep") |
193 logger.debug("Starting to monitor system sleep") |
| 184 workspace = AppKit.NSWorkspace.sharedWorkspace() |
194 workspace = AppKit.NSWorkspace.sharedWorkspace() |
| 185 notification_center = workspace.notificationCenter() |
195 notification_center = workspace.notificationCenter() |
| 186 _dreamtime_monitor[0] = SleepHandler.new() |
196 _dreamtime_monitor = SleepHandler.new() |
| 187 |
197 |
| 188 notification_center.addObserver_selector_name_object_( |
198 notification_center.addObserver_selector_name_object_( |
| 189 _dreamtime_monitor[0], |
199 _dreamtime_monitor, |
| 190 "handleSleepNotification:", |
200 "handleSleepNotification:", |
| 191 AppKit.NSWorkspaceWillSleepNotification, |
201 AppKit.NSWorkspaceWillSleepNotification, |
| 192 None) |
202 None) |
| 193 |
203 |
| 194 notification_center.addObserver_selector_name_object_( |
204 notification_center.addObserver_selector_name_object_( |
| 195 _dreamtime_monitor[0], |
205 _dreamtime_monitor, |
| 196 "handleWakeNotification:", |
206 "handleWakeNotification:", |
| 197 AppKit.NSWorkspaceDidWakeNotification, |
207 AppKit.NSWorkspaceDidWakeNotification, |
| 198 None) |
208 None) |
| 199 else: |
209 else: |
| 200 logger.warning(("No system sleep monitor implemented for '%s'" |
210 logger.warning(("No system sleep monitor implemented for '%s'" |