[libcamera-devel,v4,03/15] py: cam.py: Use new events support
diff mbox series

Message ID 20230309142601.70556-4-tomi.valkeinen@ideasonboard.com
State Superseded
Headers show
Series
  • py: New python bindings event handling
Related show

Commit Message

Tomi Valkeinen March 9, 2023, 2:25 p.m. UTC
Convert cam.py to use the new event dispatching. In addition to handling
the request-completed event, handle also disconnect, camera-added and
camera-removed events (which only do a simple print).

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
---
 src/py/cam/cam.py | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

Comments

Laurent Pinchart March 12, 2023, 3:17 p.m. UTC | #1
Hi Tomi,

Thank you for the patch.

On Thu, Mar 09, 2023 at 04:25:49PM +0200, Tomi Valkeinen via libcamera-devel wrote:
> Convert cam.py to use the new event dispatching. In addition to handling
> the request-completed event, handle also disconnect, camera-added and
> camera-removed events (which only do a simple print).
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  src/py/cam/cam.py | 28 ++++++++++++++++++++++------
>  1 file changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
> index a2a115c1..0b464256 100755
> --- a/src/py/cam/cam.py
> +++ b/src/py/cam/cam.py
> @@ -230,11 +230,20 @@ 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)
> +            evs = self.cm.get_events()
> +            for ev in evs:

You could write

            for ev in self.cm.get_events()

up to you.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +                type = ev.type
> +
> +                if type == libcam.Event.Type.CameraAdded:
> +                    print('Camera added:', ev.camera)
> +                elif type == libcam.Event.Type.CameraRemoved:
> +                    print('Camera removed:', ev.camera)
> +                elif type == libcam.Event.Type.Disconnect:
> +                    print(f'Camera {ev.camera} disconnected')
> +                elif type == libcam.Event.Type.RequestCompleted:
> +                    self.__request_handler(ev.camera, ev.request)
> +                else:
> +                    raise RuntimeError("Bad event type")
>  
>              running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts)
>              return running
> @@ -242,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))
>  
> @@ -447,6 +458,11 @@ def main():
>  
>          state.do_cmd_capture()
>  
> +        # This is not strictly needed, but it helps to do a proper cleanup as we
> +        # drop any unhandled events, and so makes it easier to use memory leak
> +        # detectors.
> +        cm.get_events()
> +
>      return 0
>  
>
Tomi Valkeinen March 13, 2023, 6:56 a.m. UTC | #2
On 12/03/2023 17:17, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Thu, Mar 09, 2023 at 04:25:49PM +0200, Tomi Valkeinen via libcamera-devel wrote:
>> Convert cam.py to use the new event dispatching. In addition to handling
>> the request-completed event, handle also disconnect, camera-added and
>> camera-removed events (which only do a simple print).
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
>> ---
>>   src/py/cam/cam.py | 28 ++++++++++++++++++++++------
>>   1 file changed, 22 insertions(+), 6 deletions(-)
>>
>> diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
>> index a2a115c1..0b464256 100755
>> --- a/src/py/cam/cam.py
>> +++ b/src/py/cam/cam.py
>> @@ -230,11 +230,20 @@ 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)
>> +            evs = self.cm.get_events()
>> +            for ev in evs:
> 
> You could write
> 
>              for ev in self.cm.get_events()
> 
> up to you.

Yes, that's a bit neater.

Also, I noticed the prints below are annoyingly using different 
styles... I'll use the inline style for all of them.

> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
>> +                type = ev.type
>> +
>> +                if type == libcam.Event.Type.CameraAdded:
>> +                    print('Camera added:', ev.camera)
>> +                elif type == libcam.Event.Type.CameraRemoved:
>> +                    print('Camera removed:', ev.camera)
>> +                elif type == libcam.Event.Type.Disconnect:
>> +                    print(f'Camera {ev.camera} disconnected')
>> +                elif type == libcam.Event.Type.RequestCompleted:
>> +                    self.__request_handler(ev.camera, ev.request)
>> +                else:
>> +                    raise RuntimeError("Bad event type")
>>   
>>               running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts)
>>               return running
>> @@ -242,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))
>>   
>> @@ -447,6 +458,11 @@ def main():
>>   
>>           state.do_cmd_capture()
>>   
>> +        # This is not strictly needed, but it helps to do a proper cleanup as we
>> +        # drop any unhandled events, and so makes it easier to use memory leak
>> +        # detectors.
>> +        cm.get_events()
>> +
>>       return 0
>>   
>>   
>

Patch
diff mbox series

diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
index a2a115c1..0b464256 100755
--- a/src/py/cam/cam.py
+++ b/src/py/cam/cam.py
@@ -230,11 +230,20 @@  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)
+            evs = self.cm.get_events()
+            for ev in evs:
+                type = ev.type
+
+                if type == libcam.Event.Type.CameraAdded:
+                    print('Camera added:', ev.camera)
+                elif type == libcam.Event.Type.CameraRemoved:
+                    print('Camera removed:', ev.camera)
+                elif type == libcam.Event.Type.Disconnect:
+                    print(f'Camera {ev.camera} disconnected')
+                elif type == libcam.Event.Type.RequestCompleted:
+                    self.__request_handler(ev.camera, ev.request)
+                else:
+                    raise RuntimeError("Bad event type")
 
             running = any(ctx.reqs_completed < ctx.opt_capture for ctx in self.contexts)
             return running
@@ -242,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))
 
@@ -447,6 +458,11 @@  def main():
 
         state.do_cmd_capture()
 
+        # This is not strictly needed, but it helps to do a proper cleanup as we
+        # drop any unhandled events, and so makes it easier to use memory leak
+        # detectors.
+        cm.get_events()
+
     return 0