summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhard Sittig <gerhard.sittig@gmx.net>2021-12-26 08:31:02 +0100
committerGerhard Sittig <gerhard.sittig@gmx.net>2021-12-26 13:45:09 +0100
commit7395d57b3c722229d18aa70fbee7e60a60902304 (patch)
tree29fc7c43174cf8d90b232f180b7698fe974895ef
parent7cfa9f7aa2426c617990f3ecfcabed8765aff46c (diff)
downloadlibsigrokdecode-7395d57b3c722229d18aa70fbee7e60a60902304.tar.gz
libsigrokdecode-7395d57b3c722229d18aa70fbee7e60a60902304.zip
ir_irmp: Python binding, support instance locking and context manager
Extend the ctypes wrapper for the IRMP decoder core. Add routines for the instance state creation and lock management. Implement metamethods for Python context managers which lock the instance to protect the C library's internal state from changing unexpectedly. Add my copyright for the non-trivial changes. This commit eliminates the limitation to a single IRMP decoder core for the sigrok process to use. Multiple Python callers can synchronize their library use, and see a consistent library state across the scope of the context manager. It's essential though that callers leave the context to not block other callers for extended periods of time.
-rw-r--r--decoders/ir_irmp/irmp_library.py69
1 files changed, 50 insertions, 19 deletions
diff --git a/decoders/ir_irmp/irmp_library.py b/decoders/ir_irmp/irmp_library.py
index 5ec6522..a1bc258 100644
--- a/decoders/ir_irmp/irmp_library.py
+++ b/decoders/ir_irmp/irmp_library.py
@@ -2,6 +2,7 @@
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2019 Rene Staffen
+## Copyright (C) 2020-2021 Gerhard Sittig <gerhard.sittig@gmx.net>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -61,12 +62,24 @@ class IrmpLibrary:
Lookup the C library's API routines. Declare their prototypes.
'''
- if not self._lib:
- return False
-
self._lib.irmp_get_sample_rate.restype = ctypes.c_uint32
self._lib.irmp_get_sample_rate.argtypes = []
+ self._lib.irmp_instance_alloc.restype = ctypes.c_void_p
+ self._lib.irmp_instance_alloc.argtypes = []
+
+ self._lib.irmp_instance_free.restype = None
+ self._lib.irmp_instance_free.argtypes = [ ctypes.c_void_p, ]
+
+ self._lib.irmp_instance_id.restype = ctypes.c_size_t
+ self._lib.irmp_instance_id.argtypes = [ ctypes.c_void_p, ]
+
+ self._lib.irmp_instance_lock.restype = ctypes.c_int
+ self._lib.irmp_instance_lock.argtypes = [ ctypes.c_void_p, ctypes.c_int, ]
+
+ self._lib.irmp_instance_unlock.restype = None
+ self._lib.irmp_instance_unlock.argtypes = [ ctypes.c_void_p, ]
+
self._lib.irmp_reset_state.restype = None
self._lib.irmp_reset_state.argtypes = []
@@ -85,6 +98,7 @@ class IrmpLibrary:
# Create a result buffer that's local to the library instance.
self._data = self.ResultData()
+ self._inst = None
return True
@@ -93,30 +107,47 @@ class IrmpLibrary:
Create a library instance.
'''
- # Only create a working instance for the first invocation.
- # Degrade all other instances, make them fail "late" during
- # execution, so that users will see the errors.
- self._lib = None
- self._data = None
- if IrmpLibrary.__usable_instance is None:
- filename = self._library_filename()
- self._lib = ctypes.cdll.LoadLibrary(filename)
- self._library_setup_api()
- IrmpLibrary.__usable_instance = self
+ filename = self._library_filename()
+ self._lib = ctypes.cdll.LoadLibrary(filename)
+ self._library_setup_api()
+
+ def __del__(self):
+ '''
+ Release a disposed library instance.
+ '''
+
+ if self._inst:
+ self._lib.irmp_instance_free(self._inst)
+ self._inst = None
+
+ def __enter__(self):
+ '''
+ Enter a context (lock management).
+ '''
+
+ if self._inst is None:
+ self._inst = self._lib.irmp_instance_alloc()
+ self._lib.irmp_instance_lock(self._inst, 1)
+ return self
+
+ def __exit__(self, extype, exvalue, trace):
+ '''
+ Leave a context (lock management).
+ '''
+
+ self._lib.irmp_instance_unlock(self._inst)
+ return False
+
+ def client_id(self):
+ return self._lib.irmp_instance_id(self._inst)
def get_sample_rate(self):
- if not self._lib:
- return None
return self._lib.irmp_get_sample_rate()
def reset_state(self):
- if not self._lib:
- return None
self._lib.irmp_reset_state()
def add_one_sample(self, level):
- if not self._lib:
- raise Exception("IRMP library limited to a single instance.")
if not self._lib.irmp_add_one_sample(int(level)):
return False
self._lib.irmp_get_result_data(ctypes.byref(self._data))