Message ID | 20220623144736.78537-8-tomi.valkeinen@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Quoting Tomi Valkeinen (2022-06-23 15:47:36) > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > src/py/cam/cam.py | 31 +++++++++++++++++++++++++------ > 1 file changed, 25 insertions(+), 6 deletions(-) > > diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py > index 733e9ae5..538f0c1d 100755 > --- a/src/py/cam/cam.py > +++ b/src/py/cam/cam.py > @@ -243,11 +243,7 @@ class CaptureState: > # Called from renderer when there is a libcamera event > def event_handler(self): > try: > - reqs = self.cm.get_ready_requests() > - > - for req in reqs: > - ctx = next(ctx for ctx in self.contexts if ctx.idx == req.cookie) > - self.__request_handler(ctx, req) > + self.cm.dispatch_events() > > running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts) > return running > @@ -255,7 +251,9 @@ class CaptureState: > traceback.print_exc() > return False > > - def __request_handler(self, ctx, req): > + def __request_handler(self, cam, req): > + ctx = next(ctx for ctx in self.contexts if ctx.camera == cam) > + > if req.status != libcam.Request.Status.Complete: > raise Exception('{}: Request failed: {}'.format(ctx.id, req.status)) > > @@ -310,6 +308,9 @@ class CaptureState: > ctx.camera.queue_request(req) > ctx.reqs_queued += 1 > > + def __disconnect_handler(self, cam): > + print('Camera', cam, 'disconnected') > + > def __capture_init(self): > for ctx in self.contexts: > ctx.acquire() > @@ -323,6 +324,15 @@ class CaptureState: > for ctx in self.contexts: > ctx.create_requests() > > + for ctx in self.contexts: > + # These cause circular dependencies: > + # The callback in the camera points to CaptureState. > + # The CaptureState points to the camera. > + # This can be solved by setting the callbacks to None after stopping > + # or using lambdas here and weakref.WeakMethod. I wish I could comment here, but I've got nothing specific or useful :S > + ctx.camera.request_completed = self.__request_handler > + ctx.camera.disconnected = self.__disconnect_handler > + > def __capture_start(self): > for ctx in self.contexts: > ctx.start() > @@ -334,6 +344,10 @@ class CaptureState: > for ctx in self.contexts: > ctx.stop() > > + for ctx in self.contexts: > + ctx.camera.request_completed = None > + ctx.camera.disconnected = None > + > for ctx in self.contexts: > ctx.release() > > @@ -402,6 +416,9 @@ def main(): > > cm = libcam.CameraManager.singleton() > > + cm.camera_added = lambda c: print("Camera added:", c) > + cm.camera_removed = lambda c: print("Camera removed:", c) > + > if args.list: > do_cmd_list(cm) > > @@ -459,6 +476,8 @@ def main(): > > state.do_cmd_capture() > > + cm.discard_events() > + > return 0 > > > -- > 2.34.1 >
Hi Tomi, Thank you for the patch. On Thu, Jun 23, 2022 at 05:47:36PM +0300, Tomi Valkeinen wrote: Maybe a commit message ? > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > src/py/cam/cam.py | 31 +++++++++++++++++++++++++------ > 1 file changed, 25 insertions(+), 6 deletions(-) > > diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py > index 733e9ae5..538f0c1d 100755 > --- a/src/py/cam/cam.py > +++ b/src/py/cam/cam.py > @@ -243,11 +243,7 @@ class CaptureState: > # Called from renderer when there is a libcamera event > def event_handler(self): > try: > - reqs = self.cm.get_ready_requests() > - > - for req in reqs: > - ctx = next(ctx for ctx in self.contexts if ctx.idx == req.cookie) > - self.__request_handler(ctx, req) > + self.cm.dispatch_events() > > running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts) > return running > @@ -255,7 +251,9 @@ class CaptureState: > traceback.print_exc() > return False > > - def __request_handler(self, ctx, req): > + def __request_handler(self, cam, req): > + ctx = next(ctx for ctx in self.contexts if ctx.camera == cam) > + > if req.status != libcam.Request.Status.Complete: > raise Exception('{}: Request failed: {}'.format(ctx.id, req.status)) > > @@ -310,6 +308,9 @@ class CaptureState: > ctx.camera.queue_request(req) > ctx.reqs_queued += 1 > > + def __disconnect_handler(self, cam): > + print('Camera', cam, 'disconnected') I thought you were a fan of Python string formatting ? :-) print(f'Camera {cam} disconnected') > + > def __capture_init(self): > for ctx in self.contexts: > ctx.acquire() > @@ -323,6 +324,15 @@ class CaptureState: > for ctx in self.contexts: > ctx.create_requests() > > + for ctx in self.contexts: > + # These cause circular dependencies: > + # The callback in the camera points to CaptureState. > + # The CaptureState points to the camera. > + # This can be solved by setting the callbacks to None after stopping > + # or using lambdas here and weakref.WeakMethod. > + ctx.camera.request_completed = self.__request_handler > + ctx.camera.disconnected = self.__disconnect_handler > + > def __capture_start(self): > for ctx in self.contexts: > ctx.start() > @@ -334,6 +344,10 @@ class CaptureState: > for ctx in self.contexts: > ctx.stop() > > + for ctx in self.contexts: > + ctx.camera.request_completed = None > + ctx.camera.disconnected = None > + > for ctx in self.contexts: > ctx.release() > > @@ -402,6 +416,9 @@ def main(): > > cm = libcam.CameraManager.singleton() > > + cm.camera_added = lambda c: print("Camera added:", c) > + cm.camera_removed = lambda c: print("Camera removed:", c) Single quotes. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > + > if args.list: > do_cmd_list(cm) > > @@ -459,6 +476,8 @@ def main(): > > state.do_cmd_capture() > > + cm.discard_events() > + > return 0 > >
diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py index 733e9ae5..538f0c1d 100755 --- a/src/py/cam/cam.py +++ b/src/py/cam/cam.py @@ -243,11 +243,7 @@ class CaptureState: # Called from renderer when there is a libcamera event def event_handler(self): try: - reqs = self.cm.get_ready_requests() - - for req in reqs: - ctx = next(ctx for ctx in self.contexts if ctx.idx == req.cookie) - self.__request_handler(ctx, req) + self.cm.dispatch_events() running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts) return running @@ -255,7 +251,9 @@ class CaptureState: traceback.print_exc() return False - def __request_handler(self, ctx, req): + def __request_handler(self, cam, req): + ctx = next(ctx for ctx in self.contexts if ctx.camera == cam) + if req.status != libcam.Request.Status.Complete: raise Exception('{}: Request failed: {}'.format(ctx.id, req.status)) @@ -310,6 +308,9 @@ class CaptureState: ctx.camera.queue_request(req) ctx.reqs_queued += 1 + def __disconnect_handler(self, cam): + print('Camera', cam, 'disconnected') + def __capture_init(self): for ctx in self.contexts: ctx.acquire() @@ -323,6 +324,15 @@ class CaptureState: for ctx in self.contexts: ctx.create_requests() + for ctx in self.contexts: + # These cause circular dependencies: + # The callback in the camera points to CaptureState. + # The CaptureState points to the camera. + # This can be solved by setting the callbacks to None after stopping + # or using lambdas here and weakref.WeakMethod. + ctx.camera.request_completed = self.__request_handler + ctx.camera.disconnected = self.__disconnect_handler + def __capture_start(self): for ctx in self.contexts: ctx.start() @@ -334,6 +344,10 @@ class CaptureState: for ctx in self.contexts: ctx.stop() + for ctx in self.contexts: + ctx.camera.request_completed = None + ctx.camera.disconnected = None + for ctx in self.contexts: ctx.release() @@ -402,6 +416,9 @@ def main(): cm = libcam.CameraManager.singleton() + cm.camera_added = lambda c: print("Camera added:", c) + cm.camera_removed = lambda c: print("Camera removed:", c) + if args.list: do_cmd_list(cm) @@ -459,6 +476,8 @@ def main(): state.do_cmd_capture() + cm.discard_events() + return 0
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- src/py/cam/cam.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)