linux observer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 149 lines 4.8 kB view raw
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3# ruff: noqa: F722, F821 4 5import logging 6import time 7from datetime import datetime 8 9from dbus_next import PropertyAccess, Variant 10from dbus_next.service import ( 11 ServiceInterface, 12 dbus_property, 13 method, 14 signal as dbus_signal, 15) 16 17logger = logging.getLogger(__name__) 18 19BUS_NAME = "org.solpbc.solstone.Observer1" 20OBJECT_PATH = "/org/solpbc/solstone/Observer1" 21 22 23class ObserverService(ServiceInterface): 24 """D-Bus service interface for the observer.""" 25 26 def __init__(self, observer): 27 super().__init__("org.solpbc.solstone.Observer1") 28 self._observer = observer 29 30 @dbus_property(access=PropertyAccess.READ) 31 def Status(self) -> "s": 32 if self._observer._paused: 33 return "paused" 34 if self._observer.current_mode == "screencast": 35 return "recording" 36 return "idle" 37 38 @dbus_property(access=PropertyAccess.READ) 39 def SyncStatus(self) -> "s": 40 if self._observer._sync: 41 return self._observer._sync.sync_status 42 return "synced" 43 44 @dbus_property(access=PropertyAccess.READ) 45 def SyncProgress(self) -> "s": 46 if self._observer._sync: 47 return self._observer._sync.sync_progress 48 return "" 49 50 @dbus_property(access=PropertyAccess.READ) 51 def CaptureDir(self) -> "s": 52 return str(self._observer.config.captures_dir) 53 54 @dbus_property(access=PropertyAccess.READ) 55 def SegmentTimer(self) -> "i": 56 if self._observer._paused or self._observer.segment_dir is None: 57 return 0 58 remaining = self._observer.interval - ( 59 time.monotonic() - self._observer.start_at_mono 60 ) 61 return max(0, int(remaining)) 62 63 @dbus_property(access=PropertyAccess.READ) 64 def PauseRemaining(self) -> "i": 65 if not self._observer._paused or self._observer._pause_until <= 0: 66 return 0 67 return max(0, int(self._observer._pause_until - time.monotonic())) 68 69 @dbus_property(access=PropertyAccess.READ) 70 def Error(self) -> "s": 71 return "" 72 73 @dbus_property(access=PropertyAccess.READ) 74 def ServerUrl(self) -> "s": 75 return self._observer.config.server_url or "" 76 77 @dbus_property(access=PropertyAccess.READ) 78 def Stream(self) -> "s": 79 return self._observer.stream 80 81 @dbus_property(access=PropertyAccess.READ) 82 def SegmentInterval(self) -> "i": 83 return self._observer.interval 84 85 @method() 86 def Pause(self, duration_seconds: "i") -> "s": 87 self._observer.pause(duration_seconds) 88 return "ok" 89 90 @method() 91 def Resume(self) -> "s": 92 self._observer.resume() 93 return "ok" 94 95 @method() 96 def GetStats(self) -> "a{sv}": 97 captures_today = 0 98 total_size = 0 99 today = datetime.now().strftime("%Y%m%d") 100 captures_dir = self._observer.config.captures_dir 101 102 try: 103 if captures_dir.exists(): 104 for day_dir in captures_dir.iterdir(): 105 if not day_dir.is_dir(): 106 continue 107 for stream_dir in day_dir.iterdir(): 108 if not stream_dir.is_dir(): 109 continue 110 for seg_dir in stream_dir.iterdir(): 111 if not seg_dir.is_dir(): 112 continue 113 if seg_dir.name.endswith(".incomplete"): 114 continue 115 if seg_dir.name.endswith(".failed"): 116 continue 117 if day_dir.name == today: 118 captures_today += 1 119 for file_path in seg_dir.iterdir(): 120 if file_path.is_file(): 121 total_size += file_path.stat().st_size 122 except OSError: 123 pass 124 125 synced_days = 0 126 if self._observer._sync: 127 synced_days = len(self._observer._sync._synced_days) 128 129 total_size_mb = int(total_size / (1024 * 1024)) 130 uptime_seconds = int(time.monotonic() - self._observer._start_mono) 131 132 return { 133 "captures_today": Variant("i", captures_today), 134 "total_size_mb": Variant("i", total_size_mb), 135 "synced_days": Variant("i", synced_days), 136 "uptime_seconds": Variant("i", uptime_seconds), 137 } 138 139 @dbus_signal() 140 def StatusChanged(self, status) -> "s": 141 return status 142 143 @dbus_signal() 144 def SyncProgressChanged(self, progress) -> "s": 145 return progress 146 147 @dbus_signal() 148 def ErrorOccurred(self, message) -> "s": 149 return message