diff --git a/EDMarketConnector.py b/EDMarketConnector.py index c8497523..67882a71 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -610,7 +610,7 @@ class AppWindow: self.w.update_idletasks() try: # Update system status on startup - if not entry['event'] and monitor.mode and monitor.system: + if entry['event'] in [None, 'StartUp'] and monitor.mode and monitor.system: self.edsm.lookup(monitor.system) # Send credits to EDSM on new game (but not on startup - data might be old) diff --git a/monitor.py b/monitor.py index bc144089..d10b9cef 100644 --- a/monitor.py +++ b/monitor.py @@ -17,6 +17,7 @@ from config import config if platform=='darwin': + from AppKit import NSWorkspace from Foundation import NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler @@ -53,6 +54,17 @@ elif platform=='win32': RegEnumKeyEx.restype = LONG RegEnumKeyEx.argtypes = [HKEY, DWORD, LPWSTR, ctypes.POINTER(DWORD), ctypes.POINTER(DWORD), LPWSTR, ctypes.POINTER(DWORD), ctypes.POINTER(FILETIME)] + EnumWindows = ctypes.windll.user32.EnumWindows + EnumWindowsProc = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM) + + CloseHandle = ctypes.windll.kernel32.CloseHandle + + GetWindowText = ctypes.windll.user32.GetWindowTextW + GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int] + GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW + + GetProcessHandleFromHwnd = ctypes.windll.oleacc.GetProcessHandleFromHwnd + else: # Linux's inotify doesn't work over CIFS or NFS, so poll FileSystemEventHandler = object # dummy @@ -234,8 +246,11 @@ class EDLogs(FileSystemEventHandler): loghandle = None if self.live: - self.event_queue.append(None) # Generate null event to update the display (with possibly out-of-date info) - self.live = False + if self.game_running(): + self.event_queue.append('{ "timestamp":"%s", "event":"StartUp" }' % strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())) + else: + self.event_queue.append(None) # Generate null event to update the display (with possibly out-of-date info) + self.live = False # Watchdog thread emitter = self.observed and self.observer._emitter_for_watch[self.observed] # Note: Uses undocumented attribute @@ -331,7 +346,8 @@ class EDLogs(FileSystemEventHandler): self.group = None elif entry['event'] == 'SetUserShipName': self.state['ShipID'] = entry['ShipID'] - self.state['ShipIdent'] = entry.get('UserShipId') + if 'UserShipId' in entry: # Only present when changing the ship's ident + self.state['ShipIdent'] = entry['UserShipId'] self.state['ShipName'] = entry.get('UserShipName') self.state['ShipType'] = entry['Ship'].lower() elif entry['event'] == 'ShipyardNew': @@ -435,6 +451,36 @@ class EDLogs(FileSystemEventHandler): return True return False + def game_running(self): + + if platform == 'darwin': + for app in NSWorkspace.sharedWorkspace().runningApplications(): + if app.bundleIdentifier() == 'uk.co.frontier.EliteDangerous': + return True + + elif platform == 'win32': + + def WindowTitle(h): + if h: + l = GetWindowTextLength(h) + 1 + buf = ctypes.create_unicode_buffer(l) + if GetWindowText(h, buf, l): + return buf.value + return None + + def callback(hWnd, lParam): + name = WindowTitle(hWnd) + if name and name.startswith('Elite - Dangerous'): + handle = GetProcessHandleFromHwnd(hWnd) + if handle: # If GetProcessHandleFromHwnd succeeds then the app is already running as this user + CloseHandle(handle) + return False # stop enumeration + return True + + return not EnumWindows(EnumWindowsProc(callback), 0) + + return False + # singleton monitor = EDLogs()