]> sigrok.org Git - libsigrokdecode.git/blame - decoders/ir_irmp/irmp_library.py
ir_irmp: Python binding, support instance locking and context manager
[libsigrokdecode.git] / decoders / ir_irmp / irmp_library.py
CommitLineData
31b646e2
GS
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2019 Rene Staffen
7395d57b 5## Copyright (C) 2020-2021 Gerhard Sittig <gerhard.sittig@gmx.net>
31b646e2
GS
6##
7## This program is free software; you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation; either version 2 of the License, or
10## (at your option) any later version.
11##
12## This program is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with this program; if not, see <http://www.gnu.org/licenses/>.
19##
20
21'''
22Python binding for the IRMP library.
23'''
24
25import ctypes
26import platform
27
28class IrmpLibrary:
29 '''
30 Library instance for an infrared protocol detector.
31 '''
32
f8c62753
GS
33 __usable_instance = None
34
31b646e2
GS
35 class ResultData(ctypes.Structure):
36 _fields_ = [
37 ( 'protocol', ctypes.c_uint32, ),
38 ( 'protocol_name', ctypes.c_char_p, ),
39 ( 'address', ctypes.c_uint32, ),
40 ( 'command', ctypes.c_uint32, ),
41 ( 'flags', ctypes.c_uint32, ),
42 ( 'start_sample', ctypes.c_uint32, ),
43 ( 'end_sample', ctypes.c_uint32, ),
44 ]
45
46 FLAG_REPETITION = 1 << 0
8c3291c7 47 FLAG_RELEASE = 1 << 1
31b646e2
GS
48
49 def _library_filename(self):
50 '''
51 Determine the library filename depending on the platform.
52 '''
53
54 if platform.uname()[0] == 'Linux':
55 return 'libirmp.so'
02993c7a
GS
56 if platform.uname()[0] == 'Darwin':
57 return 'libirmp.dylib'
31b646e2
GS
58 return 'irmp.dll'
59
f8c62753 60 def _library_setup_api(self):
31b646e2 61 '''
f8c62753 62 Lookup the C library's API routines. Declare their prototypes.
31b646e2
GS
63 '''
64
31b646e2
GS
65 self._lib.irmp_get_sample_rate.restype = ctypes.c_uint32
66 self._lib.irmp_get_sample_rate.argtypes = []
67
7395d57b
GS
68 self._lib.irmp_instance_alloc.restype = ctypes.c_void_p
69 self._lib.irmp_instance_alloc.argtypes = []
70
71 self._lib.irmp_instance_free.restype = None
72 self._lib.irmp_instance_free.argtypes = [ ctypes.c_void_p, ]
73
74 self._lib.irmp_instance_id.restype = ctypes.c_size_t
75 self._lib.irmp_instance_id.argtypes = [ ctypes.c_void_p, ]
76
77 self._lib.irmp_instance_lock.restype = ctypes.c_int
78 self._lib.irmp_instance_lock.argtypes = [ ctypes.c_void_p, ctypes.c_int, ]
79
80 self._lib.irmp_instance_unlock.restype = None
81 self._lib.irmp_instance_unlock.argtypes = [ ctypes.c_void_p, ]
82
31b646e2
GS
83 self._lib.irmp_reset_state.restype = None
84 self._lib.irmp_reset_state.argtypes = []
85
86 self._lib.irmp_add_one_sample.restype = ctypes.c_int
87 self._lib.irmp_add_one_sample.argtypes = [ ctypes.c_int, ]
88
89 if False:
90 self._lib.irmp_detect_buffer.restype = self.ResultData
91 self._lib.irmp_detect_buffer.argtypes = [ ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t, ]
92
93 self._lib.irmp_get_result_data.restype = ctypes.c_int
94 self._lib.irmp_get_result_data.argtypes = [ ctypes.POINTER(self.ResultData), ]
95
96 self._lib.irmp_get_protocol_name.restype = ctypes.c_char_p
97 self._lib.irmp_get_protocol_name.argtypes = [ ctypes.c_uint32, ]
98
99 # Create a result buffer that's local to the library instance.
100 self._data = self.ResultData()
7395d57b 101 self._inst = None
31b646e2 102
f8c62753
GS
103 return True
104
105 def __init__(self):
106 '''
107 Create a library instance.
108 '''
109
7395d57b
GS
110 filename = self._library_filename()
111 self._lib = ctypes.cdll.LoadLibrary(filename)
112 self._library_setup_api()
113
114 def __del__(self):
115 '''
116 Release a disposed library instance.
117 '''
118
119 if self._inst:
120 self._lib.irmp_instance_free(self._inst)
121 self._inst = None
122
123 def __enter__(self):
124 '''
125 Enter a context (lock management).
126 '''
127
128 if self._inst is None:
129 self._inst = self._lib.irmp_instance_alloc()
130 self._lib.irmp_instance_lock(self._inst, 1)
131 return self
132
133 def __exit__(self, extype, exvalue, trace):
134 '''
135 Leave a context (lock management).
136 '''
137
138 self._lib.irmp_instance_unlock(self._inst)
139 return False
140
141 def client_id(self):
142 return self._lib.irmp_instance_id(self._inst)
f8c62753 143
31b646e2
GS
144 def get_sample_rate(self):
145 return self._lib.irmp_get_sample_rate()
146
147 def reset_state(self):
148 self._lib.irmp_reset_state()
149
150 def add_one_sample(self, level):
151 if not self._lib.irmp_add_one_sample(int(level)):
152 return False
153 self._lib.irmp_get_result_data(ctypes.byref(self._data))
154 return True
155
156 def get_result_data(self):
f8c62753
GS
157 if not self._data:
158 return None
159 return {
31b646e2
GS
160 'proto_nr': self._data.protocol,
161 'proto_name': self._data.protocol_name.decode('UTF-8', 'ignore'),
162 'address': self._data.address,
163 'command': self._data.command,
164 'repeat': bool(self._data.flags & self.FLAG_REPETITION),
8c3291c7 165 'release': bool(self._data.flags & self.FLAG_RELEASE),
31b646e2
GS
166 'start': self._data.start_sample,
167 'end': self._data.end_sample,
168 }