]> sigrok.org Git - libsigrok.git/blame_incremental - bindings/python/sigrok/core/classes.i
Remove SR_OK_CONTINUE.
[libsigrok.git] / bindings / python / sigrok / core / classes.i
... / ...
CommitLineData
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2014 Martin Ling <martin-sigrok@earth.li>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20%define DOCSTRING
21"@mainpage API Reference
22
23Introduction
24------------
25
26The pysigrok API provides an object-oriented Python interface to the
27functionality in libsigrok. It is built on top of the libsigrokcxx C++ API.
28
29Getting started
30---------------
31
32Usage of the pysigrok API needs to begin with a call to Context.create().
33This will create the global libsigrok context and returns a Context object.
34Methods on this object provide access to the hardware drivers, input and output
35formats supported by the library, as well as means of creating other objects
36such as sessions and triggers.
37
38Error handling
39--------------
40
41When any libsigrok C API call returns an error, an Error exception is raised,
42which provides access to the error code and description."
43%enddef
44
45%module(docstring=DOCSTRING) classes
46
47%{
48#include <stdio.h>
49#include <pygobject.h>
50#include <numpy/arrayobject.h>
51
52PyObject *PyGObject_lib;
53PyObject *GLib;
54PyTypeObject *IOChannel;
55PyTypeObject *PollFD;
56
57#include "config.h"
58
59#if PYGOBJECT_FLAGS_SIGNED
60typedef gint pyg_flags_type;
61#else
62typedef guint pyg_flags_type;
63#endif
64
65%}
66
67%init %{
68 PyGObject_lib = pygobject_init(-1, -1, -1);
69 if (!PyGObject_lib)
70 fprintf(stderr, "pygobject initialization failed.\n");
71 GLib = PyImport_ImportModule("gi.repository.GLib");
72 /*
73 * This check can't save us if the import fails, but at least it gives us
74 * a starting point to trace the issue versus straight out crashing.
75 */
76 if (!GLib) {
77 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
78 return;
79 }
80 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
81 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
82 import_array();
83%}
84
85/* Map file objects to file descriptors. */
86%typecheck(SWIG_TYPECHECK_POINTER) int fd {
87 $1 = (PyObject_AsFileDescriptor($input) != -1);
88}
89
90%typemap(in) int fd {
91 int fd = PyObject_AsFileDescriptor($input);
92 if (fd == -1)
93 SWIG_exception(SWIG_TypeError,
94 "Expected file object or integer file descriptor");
95 else
96 $1 = fd;
97}
98
99/* Map from Glib::Variant to native Python types. */
100%typemap(out) Glib::VariantBase {
101 GValue *value = g_new0(GValue, 1);
102 g_value_init(value, G_TYPE_VARIANT);
103 g_value_set_variant(value, $1.gobj());
104 PyObject *variant = pyg_value_as_pyobject(value, true);
105 $result = PyObject_CallMethod(variant,
106 const_cast<char *>("unpack"),
107 const_cast<char *>(""), NULL);
108 Py_XDECREF(variant);
109 g_free(value);
110}
111
112/* Map from Glib::IOCondition to GLib.IOCondition. */
113%typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
114 pyg_flags_type flags;
115 $1 = pygobject_check($input, &PyGFlags_Type) &&
116 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
117}
118
119%typemap(in) Glib::IOCondition {
120 if (!pygobject_check($input, &PyGFlags_Type))
121 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
122 pyg_flags_type flags;
123 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
124 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
125 $1 = (Glib::IOCondition) flags;
126}
127
128/* And back */
129%typemap(out) Glib::IOCondition {
130 GValue *value = g_new0(GValue, 1);
131 g_value_init(value, G_TYPE_IO_CONDITION);
132 g_value_set_flags(value, &$1);
133 $result = pyg_value_as_pyobject(value, true);
134 g_free(value);
135}
136
137/* Map from GLib.PollFD to Glib::PollFD *. */
138%typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
139 $1 = pygobject_check($input, PollFD);
140}
141
142%typemap(in) Glib::PollFD {
143 if (!pygobject_check($input, PollFD))
144 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
145 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
146 PyObject *events_obj = PyObject_GetAttrString($input, "events");
147 pyg_flags_type flags;
148 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
149 int fd = PyInt_AsLong(fd_obj);
150 Glib::IOCondition events = (Glib::IOCondition) flags;
151 $1 = Glib::PollFD(fd, events);
152}
153
154/* Map from GLib.IOChannel to Glib::IOChannel *. */
155%typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
156 $1 = pygobject_check($input, IOChannel);
157}
158
159%typemap(in) Glib::RefPtr<Glib::IOChannel> {
160 if (!pygobject_check($input, IOChannel))
161 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
162 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
163}
164
165/* Map from callable PyObject to SourceCallbackFunction. */
166%typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
167 $1 = PyCallable_Check($input);
168}
169
170%typemap(in) sigrok::SourceCallbackFunction {
171 if (!PyCallable_Check($input))
172 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
173
174 $1 = [=] (Glib::IOCondition revents) {
175 auto gstate = PyGILState_Ensure();
176
177 GValue *value = g_new0(GValue, 1);
178 g_value_init(value, G_TYPE_IO_CONDITION);
179 g_value_set_flags(value, revents);
180 auto revents_obj = pyg_value_as_pyobject(value, true);
181 g_free(value);
182
183 auto arglist = Py_BuildValue("(O)", revents_obj);
184
185 auto result = PyEval_CallObject($input, arglist);
186
187 Py_XDECREF(arglist);
188 Py_XDECREF(revents_obj);
189
190 bool completed = !PyErr_Occurred();
191
192 if (!completed)
193 PyErr_Print();
194
195 bool valid_result = (completed && PyBool_Check(result));
196
197 if (completed && !valid_result)
198 {
199 PyErr_SetString(PyExc_TypeError,
200 "EventSource callback did not return a boolean");
201 PyErr_Print();
202 }
203
204 bool retval = (valid_result && result == Py_True);
205
206 Py_XDECREF(result);
207
208 PyGILState_Release(gstate);
209
210 if (!valid_result)
211 throw sigrok::Error(SR_ERR);
212
213 return retval;
214 };
215
216 Py_XINCREF($input);
217}
218
219/* Map from callable PyObject to LogCallbackFunction */
220%typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
221 $1 = PyCallable_Check($input);
222}
223
224%typemap(in) sigrok::LogCallbackFunction {
225 if (!PyCallable_Check($input))
226 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
227
228 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
229 auto gstate = PyGILState_Ensure();
230
231 auto log_obj = SWIG_NewPointerObj(
232 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
233
234 auto string_obj = PyString_FromString(message.c_str());
235
236 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
237
238 auto result = PyEval_CallObject($input, arglist);
239
240 Py_XDECREF(arglist);
241 Py_XDECREF(log_obj);
242 Py_XDECREF(string_obj);
243
244 bool completed = !PyErr_Occurred();
245
246 if (!completed)
247 PyErr_Print();
248
249 bool valid_result = (completed && result == Py_None);
250
251 Py_XDECREF(result);
252
253 if (completed && !valid_result)
254 {
255 PyErr_SetString(PyExc_TypeError,
256 "Log callback did not return None");
257 PyErr_Print();
258 }
259
260 PyGILState_Release(gstate);
261
262 if (!valid_result)
263 throw sigrok::Error(SR_ERR);
264 };
265
266 Py_XINCREF($input);
267}
268
269/* Map from callable PyObject to DatafeedCallbackFunction */
270%typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
271 $1 = PyCallable_Check($input);
272}
273
274%typemap(in) sigrok::DatafeedCallbackFunction {
275 if (!PyCallable_Check($input))
276 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
277
278 $1 = [=] (std::shared_ptr<sigrok::Device> device,
279 std::shared_ptr<sigrok::Packet> packet) {
280 auto gstate = PyGILState_Ensure();
281
282 auto device_obj = SWIG_NewPointerObj(
283 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
284 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
285
286 auto packet_obj = SWIG_NewPointerObj(
287 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
288 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
289
290 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
291
292 auto result = PyEval_CallObject($input, arglist);
293
294 Py_XDECREF(arglist);
295 Py_XDECREF(device_obj);
296 Py_XDECREF(packet_obj);
297
298 bool completed = !PyErr_Occurred();
299
300 if (!completed)
301 PyErr_Print();
302
303 bool valid_result = (completed && result == Py_None);
304
305 Py_XDECREF(result);
306
307 if (completed && !valid_result)
308 {
309 PyErr_SetString(PyExc_TypeError,
310 "Datafeed callback did not return None");
311 PyErr_Print();
312 }
313
314 PyGILState_Release(gstate);
315
316 if (!valid_result)
317 throw sigrok::Error(SR_ERR);
318 };
319
320 Py_XINCREF($input);
321}
322
323/* Cast PacketPayload pointers to correct subclass type. */
324%ignore sigrok::Packet::payload;
325
326%extend sigrok::Packet
327{
328 std::shared_ptr<sigrok::Header> _payload_header()
329 {
330 return dynamic_pointer_cast<sigrok::Header>($self->payload());
331 }
332 std::shared_ptr<sigrok::Meta> _payload_meta()
333 {
334 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
335 }
336 std::shared_ptr<sigrok::Analog> _payload_analog()
337 {
338 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
339 }
340 std::shared_ptr<sigrok::Logic> _payload_logic()
341 {
342 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
343 }
344}
345
346%extend sigrok::Packet
347{
348%pythoncode
349{
350 def _payload(self):
351 if self.type == PacketType.HEADER:
352 return self._payload_header()
353 elif self.type == PacketType.META:
354 return self._payload_meta()
355 elif self.type == PacketType.LOGIC:
356 return self._payload_logic()
357 elif self.type == PacketType.ANALOG:
358 return self._payload_analog()
359 else:
360 return None
361
362 payload = property(_payload)
363}
364}
365
366%{
367
368#include "libsigrokcxx/libsigrokcxx.hpp"
369
370/* Convert from a Python dict to a std::map<std::string, std::string> */
371std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
372{
373 if (!PyDict_Check(dict))
374 throw sigrok::Error(SR_ERR_ARG);
375
376 std::map<std::string, std::string> output;
377
378 PyObject *py_key, *py_value;
379 Py_ssize_t pos = 0;
380
381 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
382 if (!PyString_Check(py_key))
383 throw sigrok::Error(SR_ERR_ARG);
384 if (!PyString_Check(py_value))
385 throw sigrok::Error(SR_ERR_ARG);
386 auto key = PyString_AsString(py_key);
387 auto value = PyString_AsString(py_value);
388 output[key] = value;
389 }
390
391 return output;
392}
393
394/* Convert from a Python type to Glib::Variant, according to config key data type. */
395Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
396{
397 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
398
399 if (type == SR_T_UINT64 && PyInt_Check(input))
400 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
401 if (type == SR_T_UINT64 && PyLong_Check(input))
402 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
403 else if (type == SR_T_STRING && PyString_Check(input))
404 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
405 else if (type == SR_T_BOOL && PyBool_Check(input))
406 return Glib::Variant<bool>::create(input == Py_True);
407 else if (type == SR_T_FLOAT && PyFloat_Check(input))
408 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
409 else if (type == SR_T_INT32 && PyInt_Check(input))
410 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
411 else
412 throw sigrok::Error(SR_ERR_ARG);
413}
414
415/* Convert from a Python type to Glib::Variant, according to Option data type. */
416Glib::VariantBase python_to_variant_by_option(PyObject *input,
417 std::shared_ptr<sigrok::Option> option)
418{
419 GVariantType *type = option->default_value().get_type().gobj();
420
421 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
422 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
423 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
424 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
425 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
426 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
427 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
428 return Glib::Variant<bool>::create(input == Py_True);
429 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
430 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
431 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
432 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
433 else
434 throw sigrok::Error(SR_ERR_ARG);
435}
436
437/* Convert from a Python dict to a std::map<std::string, std::string> */
438std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
439 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
440{
441 if (!PyDict_Check(dict))
442 throw sigrok::Error(SR_ERR_ARG);
443
444 std::map<std::string, Glib::VariantBase> output;
445
446 PyObject *py_key, *py_value;
447 Py_ssize_t pos = 0;
448
449 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
450 if (!PyString_Check(py_key))
451 throw sigrok::Error(SR_ERR_ARG);
452 auto key = PyString_AsString(py_key);
453 auto value = python_to_variant_by_option(py_value, options[key]);
454 output[key] = value;
455 }
456
457 return output;
458}
459
460%}
461
462/* Ignore these methods, we will override them below. */
463%ignore sigrok::Analog::data;
464%ignore sigrok::Driver::scan;
465%ignore sigrok::InputFormat::create_input;
466%ignore sigrok::OutputFormat::create_output;
467
468%include "doc.i"
469
470%define %attributevector(Class, Type, Name, Get)
471%rename(_ ## Get) sigrok::Class::Get;
472%extend sigrok::Class
473{
474%pythoncode
475{
476 Name = property(_ ## Get)
477}
478}
479%enddef
480
481%define %attributemap(Class, Type, Name, Get)
482%rename(_ ## Get) sigrok::Class::Get;
483%extend sigrok::Class
484{
485%pythoncode
486{
487 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
488}
489}
490%enddef
491
492%define %enumextras(Class)
493%extend sigrok::Class
494{
495 long __hash__()
496 {
497 return (long) $self;
498 }
499
500%pythoncode
501{
502 def __eq__(self, other):
503 return (type(self) is type(other) and hash(self) == hash(other))
504
505 def __ne__(self, other):
506 return (type(self) is not type(other) or hash(self) != hash(other))
507}
508}
509%enddef
510
511%include "../../../swig/classes.i"
512
513/* Support Driver.scan() with keyword arguments. */
514%extend sigrok::Driver
515{
516 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
517 {
518 if (!PyDict_Check(dict))
519 throw sigrok::Error(SR_ERR_ARG);
520
521 PyObject *py_key, *py_value;
522 Py_ssize_t pos = 0;
523 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
524
525 while (PyDict_Next(dict, &pos, &py_key, &py_value))
526 {
527 if (!PyString_Check(py_key))
528 throw sigrok::Error(SR_ERR_ARG);
529 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
530 auto value = python_to_variant_by_key(py_value, key);
531 options[key] = value;
532 }
533
534 return $self->scan(options);
535 }
536}
537
538%pythoncode
539{
540 def _Driver_scan(self, **kwargs):
541 return self._scan_kwargs(kwargs)
542
543 Driver.scan = _Driver_scan
544}
545
546/* Support InputFormat.create_input() with keyword arguments. */
547%extend sigrok::InputFormat
548{
549 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
550 {
551 return $self->create_input(
552 dict_to_map_options(dict, $self->options()));
553 }
554}
555
556%pythoncode
557{
558 def _InputFormat_create_input(self, **kwargs):
559 return self._create_input(kwargs)
560
561 InputFormat.create_input = _InputFormat_create_input
562}
563
564/* Support OutputFormat.create_output() with keyword arguments. */
565%extend sigrok::OutputFormat
566{
567 std::shared_ptr<sigrok::Output> _create_output_kwargs(
568 std::shared_ptr<sigrok::Device> device, PyObject *dict)
569 {
570 return $self->create_output(device,
571 dict_to_map_options(dict, $self->options()));
572 }
573}
574
575%pythoncode
576{
577 def _OutputFormat_create_output(self, device, **kwargs):
578 return self._create_output_kwargs(device, kwargs)
579
580 OutputFormat.create_output = _OutputFormat_create_output
581}
582
583/* Support config_set() with Python input types. */
584%extend sigrok::Configurable
585{
586 void config_set(const ConfigKey *key, PyObject *input)
587 {
588 $self->config_set(key, python_to_variant_by_key(input, key));
589 }
590}
591
592/* Return NumPy array from Analog::data(). */
593%extend sigrok::Analog
594{
595 PyObject * _data()
596 {
597 int nd = 2;
598 npy_intp dims[2];
599 dims[0] = $self->channels().size();
600 dims[1] = $self->num_samples();
601 int typenum = NPY_FLOAT;
602 void *data = $self->data_pointer();
603 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
604 }
605
606%pythoncode
607{
608 data = property(_data)
609}
610}