@@ -101,6 +101,14 @@ def _worker() -> None:
101101 threading .Thread (target = _worker , daemon = True ).start ()
102102
103103 def _on_detection_done (self , cameras : list [CameraInfo ]) -> bool :
104+ # Preserve manually-added cameras (IP, phone) across hotplug scans
105+ manual_backends = {BackendType .IP , BackendType .PHONE }
106+ manual_cameras = [c for c in self ._cameras if c .backend in manual_backends ]
107+ seen_ids = {c .id for c in cameras }
108+ for mc in manual_cameras :
109+ if mc .id not in seen_ids :
110+ cameras .append (mc )
111+
104112 old_ids = {c .id for c in self ._cameras }
105113 new_ids = {c .id for c in cameras }
106114 self ._cameras = cameras
@@ -120,6 +128,19 @@ def add_ip_cameras(self, entries: list[dict[str, str]]) -> None:
120128 self ._cameras .extend (ip_cams )
121129 self .emit ("cameras-changed" )
122130
131+ def add_phone_camera (self , camera : CameraInfo ) -> None :
132+ """Register a phone camera source (WebRTC)."""
133+ self ._cameras = [c for c in self ._cameras if c .backend != BackendType .PHONE ]
134+ self ._cameras .append (camera )
135+ self .emit ("cameras-changed" )
136+
137+ def remove_phone_camera (self ) -> None :
138+ """Remove phone camera from the list."""
139+ had = any (c .backend == BackendType .PHONE for c in self ._cameras )
140+ self ._cameras = [c for c in self ._cameras if c .backend != BackendType .PHONE ]
141+ if had :
142+ self .emit ("cameras-changed" )
143+
123144 # -- controls proxy ------------------------------------------------------
124145
125146 def get_controls (self , camera : CameraInfo ) -> list [CameraControl ]:
0 commit comments