libsigrokcxx  unreleased development snapshot
C++ bindings for libsigrok
libsigrokcxx.hpp
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013-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 /**
21 
22 @mainpage API Reference
23 
24 Introduction
25 ------------
26 
27 The libsigrokcxx API provides an object-oriented C++ interface to the
28 functionality in libsigrok, including automatic memory and resource management.
29 
30 It is built on top of the public libsigrok C API, and is designed to be used as
31 a standalone alternative API. Programs should not mix usage of the C and C++
32 APIs; the C++ interface code needs to have full control of all C API calls for
33 resources to be managed correctly.
34 
35 Memory management
36 -----------------
37 
38 All runtime objects created through the C++ API are passed and accessed via
39 shared pointers, using the C++11 std::shared_ptr implementation. This means
40 that a reference count is kept for each object.
41 
42 Shared pointers can be copied and assigned in a user's program, automatically
43 updating their reference count and deleting objects when they are no longer in
44 use. The C++ interface code also keeps track of internal dependencies between
45 libsigrok resources, and ensures that objects are not prematurely deleted when
46 their resources are in use by other objects.
47 
48 This means that management of libsigrokcxx objects and their underlying
49 libsigrok resources can be treated as fully automatic. As long as all shared
50 pointers to objects are deleted or reassigned when no longer in use, all
51 underlying resources will be released at the right time.
52 
53 Getting started
54 ---------------
55 
56 Usage of the C++ API needs to begin with a call to sigrok::Context::create().
57 This will create the global libsigrok context and returns a shared pointer to
58 the sigrok::Context object. Methods on this object provide access to the
59 hardware drivers, input and output formats supported by the library, as well
60 as means of creating other objects such as sessions and triggers.
61 
62 Error handling
63 --------------
64 
65 When any libsigrok C API call returns an error, a sigrok::Error exception is
66 raised, which provides access to the error code and description.
67 
68 */
69 
70 #ifndef LIBSIGROKCXX_HPP
71 #define LIBSIGROKCXX_HPP
72 
73 #include <libsigrok/libsigrok.h>
74 
75 /* Suppress warnings due to glibmm's use of std::auto_ptr<> in a public
76  * header file. To be removed once glibmm is fixed. */
77 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
78 #include <glibmm.h>
79 G_GNUC_END_IGNORE_DEPRECATIONS
80 
81 #include <functional>
82 #include <stdexcept>
83 #include <memory>
84 #include <vector>
85 #include <map>
86 #include <set>
87 
88 namespace sigrok
89 {
90 
91 /* Forward declarations */
92 class SR_API Error;
93 class SR_API Context;
94 class SR_API Driver;
95 class SR_API Device;
96 class SR_API HardwareDevice;
97 class SR_API Channel;
98 class SR_API Session;
99 class SR_API ConfigKey;
100 class SR_API Capability;
101 class SR_API InputFormat;
102 class SR_API OutputFormat;
103 class SR_API OutputFlag;
104 class SR_API LogLevel;
105 class SR_API ChannelGroup;
106 class SR_API Trigger;
107 class SR_API TriggerStage;
108 class SR_API TriggerMatch;
109 class SR_API TriggerMatchType;
110 class SR_API ChannelType;
111 class SR_API Packet;
112 class SR_API PacketPayload;
113 class SR_API PacketType;
114 class SR_API Quantity;
115 class SR_API Unit;
116 class SR_API QuantityFlag;
117 class SR_API Rational;
118 class SR_API Input;
119 class SR_API InputDevice;
120 class SR_API Output;
121 class SR_API DataType;
122 class SR_API Option;
123 class SR_API UserDevice;
124 
125 /** Exception thrown when an error code is returned by any libsigrok call. */
126 class SR_API Error: public std::exception
127 {
128 public:
129  explicit Error(int result);
130  ~Error() noexcept;
131  const int result;
132  const char *what() const noexcept;
133 };
134 
135 /* Base template for classes whose resources are owned by a parent object. */
136 template <class Class, class Parent>
137 class SR_API ParentOwned
138 {
139 private:
140  /* Weak pointer for shared_from_this() implementation. */
141  std::weak_ptr<Class> _weak_this;
142 
143  static void reset_parent(Class *object)
144  {
145  if (!object->_parent)
146  throw Error(SR_ERR_BUG);
147  object->_parent.reset();
148  }
149 
150 protected:
151  /* Parent object which owns this child object's underlying structure.
152 
153  This shared pointer will be null when this child is unused, but
154  will be assigned to point to the parent before any shared pointer
155  to this child is handed out to the user.
156 
157  When the reference count of this child falls to zero, this shared
158  pointer to its parent is reset by a custom deleter on the child's
159  shared pointer.
160 
161  This strategy ensures that the destructors for both the child and
162  the parent are called at the correct time, i.e. only when all
163  references to both the parent and all its children are gone. */
164  std::shared_ptr<Parent> _parent;
165 
166  ParentOwned() {}
167 
168  /* Note, this implementation will create a new smart_ptr if none exists. */
169  std::shared_ptr<Class> shared_from_this()
170  {
171  std::shared_ptr<Class> shared = _weak_this.lock();
172 
173  if (!shared)
174  {
175  shared.reset(static_cast<Class *>(this), &reset_parent);
176  _weak_this = shared;
177  }
178 
179  return shared;
180  }
181 
182  std::shared_ptr<Class> share_owned_by(std::shared_ptr<Parent> parent)
183  {
184  if (!parent)
185  throw Error(SR_ERR_BUG);
186  this->_parent = parent;
187  return shared_from_this();
188  }
189 
190 public:
191  /* Get parent object that owns this object. */
192  std::shared_ptr<Parent> parent()
193  {
194  return _parent;
195  }
196 };
197 
198 /* Base template for classes whose resources are owned by the user. */
199 template <class Class>
200 class SR_API UserOwned : public std::enable_shared_from_this<Class>
201 {
202 protected:
203  UserOwned() {}
204 
205  std::shared_ptr<Class> shared_from_this()
206  {
207  auto shared = std::enable_shared_from_this<Class>::shared_from_this();
208  if (!shared)
209  throw Error(SR_ERR_BUG);
210  return shared;
211  }
212 };
213 
214 /** Type of log callback */
215 typedef std::function<void(const LogLevel *, std::string message)> LogCallbackFunction;
216 
217 /** Resource reader delegate. */
218 class SR_API ResourceReader
219 {
220 public:
221  ResourceReader() {}
222  virtual ~ResourceReader();
223 private:
224  /** Resource open hook. */
225  virtual void open(struct sr_resource *res, std::string name) = 0;
226  /** Resource close hook. */
227  virtual void close(struct sr_resource *res) = 0;
228  /** Resource read hook. */
229  virtual size_t read(const struct sr_resource *res, void *buf, size_t count) = 0;
230 
231  static SR_PRIV int open_callback(struct sr_resource *res,
232  const char *name, void *cb_data) noexcept;
233  static SR_PRIV int close_callback(struct sr_resource *res,
234  void *cb_data) noexcept;
235  static SR_PRIV gssize read_callback(const struct sr_resource *res,
236  void *buf, size_t count, void *cb_data) noexcept;
237  friend class Context;
238 };
239 
240 /** The global libsigrok context */
241 class SR_API Context : public UserOwned<Context>
242 {
243 public:
244  /** Create new context */
245  static std::shared_ptr<Context> create();
246  /** libsigrok package version. */
247  static std::string package_version();
248  /** libsigrok library version. */
249  static std::string lib_version();
250  /** Available hardware drivers, indexed by name. */
251  std::map<std::string, std::shared_ptr<Driver> > drivers();
252  /** Available input formats, indexed by name. */
253  std::map<std::string, std::shared_ptr<InputFormat> > input_formats();
254  /** Lookup the responsible input module for an input file. */
255  std::shared_ptr<InputFormat> input_format_match(std::string filename);
256  /** Available output formats, indexed by name. */
257  std::map<std::string, std::shared_ptr<OutputFormat> > output_formats();
258  /** Current log level. */
259  const LogLevel *log_level() const;
260  /** Set the log level.
261  * @param level LogLevel to use. */
262  void set_log_level(const LogLevel *level);
263  /** Set the log callback.
264  * @param callback Callback of the form callback(LogLevel, string). */
265  void set_log_callback(LogCallbackFunction callback);
266  /** Set the log callback to the default handler. */
267  void set_log_callback_default();
268  /** Install a delegate for reading resource files.
269  * @param reader The resource reader delegate, or nullptr to unset. */
270  void set_resource_reader(ResourceReader *reader);
271  /** Create a new session. */
272  std::shared_ptr<Session> create_session();
273  /** Create a new user device. */
274  std::shared_ptr<UserDevice> create_user_device(
275  std::string vendor, std::string model, std::string version);
276  /** Create a header packet. */
277  std::shared_ptr<Packet> create_header_packet(Glib::DateTime start_time);
278  /** Create a meta packet. */
279  std::shared_ptr<Packet> create_meta_packet(
280  std::map<const ConfigKey *, Glib::VariantBase> config);
281  /** Create a logic packet. */
282  std::shared_ptr<Packet> create_logic_packet(
283  void *data_pointer, size_t data_length, unsigned int unit_size);
284  /** Create an analog packet. */
285  std::shared_ptr<Packet> create_analog_packet(
286  std::vector<std::shared_ptr<Channel> > channels,
287  const float *data_pointer, unsigned int num_samples, const Quantity *mq,
288  const Unit *unit, std::vector<const QuantityFlag *> mqflags);
289  /** Create an end packet. */
290  std::shared_ptr<Packet> create_end_packet();
291  /** Load a saved session.
292  * @param filename File name string. */
293  std::shared_ptr<Session> load_session(std::string filename);
294  /** Create a new trigger.
295  * @param name Name string for new trigger. */
296  std::shared_ptr<Trigger> create_trigger(std::string name);
297  /** Open an input file.
298  * @param filename File name string. */
299  std::shared_ptr<Input> open_file(std::string filename);
300  /** Open an input stream based on header data.
301  * @param header Initial data from stream. */
302  std::shared_ptr<Input> open_stream(std::string header);
303  std::map<std::string, std::string> serials(std::shared_ptr<Driver> driver) const;
304 private:
305  struct sr_context *_structure;
306  std::map<std::string, std::unique_ptr<Driver> > _drivers;
307  std::map<std::string, std::unique_ptr<InputFormat> > _input_formats;
308  std::map<std::string, std::unique_ptr<OutputFormat> > _output_formats;
309  Session *_session;
310  LogCallbackFunction _log_callback;
311  Context();
312  ~Context();
313  friend class Session;
314  friend class Driver;
315  friend struct std::default_delete<Context>;
316 };
317 
318 /** An object that can be configured. */
319 class SR_API Configurable
320 {
321 public:
322  /** Supported configuration keys. */
323  std::set<const ConfigKey *> config_keys() const;
324  /** Read configuration for the given key.
325  * @param key ConfigKey to read. */
326  Glib::VariantBase config_get(const ConfigKey *key) const;
327  /** Set configuration for the given key to a specified value.
328  * @param key ConfigKey to set.
329  * @param value Value to set. */
330  void config_set(const ConfigKey *key, const Glib::VariantBase &value);
331  /** Enumerate available values for the given configuration key.
332  * @param key ConfigKey to enumerate values for. */
333  Glib::VariantContainerBase config_list(const ConfigKey *key) const;
334  /** Enumerate configuration capabilities for the given configuration key.
335  * @param key ConfigKey to enumerate capabilities for. */
336  std::set<const Capability *> config_capabilities(const ConfigKey *key) const;
337  /** Check whether a configuration capability is supported for a given key.
338  * @param key ConfigKey to check.
339  * @param capability Capability to check for. */
340  bool config_check(const ConfigKey *key, const Capability *capability) const;
341 protected:
342  Configurable(
343  struct sr_dev_driver *driver,
344  struct sr_dev_inst *sdi,
345  struct sr_channel_group *channel_group);
346  virtual ~Configurable();
347  struct sr_dev_driver *config_driver;
348  struct sr_dev_inst *config_sdi;
349  struct sr_channel_group *config_channel_group;
350 };
351 
352 /** A hardware driver provided by the library */
353 class SR_API Driver : public ParentOwned<Driver, Context>, public Configurable
354 {
355 public:
356  /** Name of this driver. */
357  std::string name() const;
358  /** Long name for this driver. */
359  std::string long_name() const;
360  /** Scan options supported by this driver. */
361  std::set<const ConfigKey *> scan_options() const;
362  /** Scan for devices and return a list of devices found.
363  * @param options Mapping of (ConfigKey, value) pairs. */
364  std::vector<std::shared_ptr<HardwareDevice> > scan(std::map<const ConfigKey *, Glib::VariantBase>
365  options = std::map<const ConfigKey *, Glib::VariantBase>());
366 private:
367  struct sr_dev_driver *_structure;
368  bool _initialized;
369  std::vector<HardwareDevice *> _devices;
370  explicit Driver(struct sr_dev_driver *structure);
371  ~Driver();
372  friend class Context;
373  friend class HardwareDevice;
374  friend class ChannelGroup;
375  friend struct std::default_delete<Driver>;
376 };
377 
378 /** A generic device, either hardware or virtual */
379 class SR_API Device : public Configurable
380 {
381 public:
382  /** Vendor name for this device. */
383  std::string vendor() const;
384  /** Model name for this device. */
385  std::string model() const;
386  /** Version string for this device. */
387  std::string version() const;
388  /** Serial number for this device. */
389  std::string serial_number() const;
390  /** Connection ID for this device. */
391  std::string connection_id() const;
392  /** List of the channels available on this device. */
393  std::vector<std::shared_ptr<Channel> > channels();
394  /** Channel groups available on this device, indexed by name. */
395  std::map<std::string, std::shared_ptr<ChannelGroup> > channel_groups();
396  /** Open device. */
397  void open();
398  /** Close device. */
399  void close();
400 protected:
401  explicit Device(struct sr_dev_inst *structure);
402  ~Device();
403  virtual std::shared_ptr<Device> get_shared_from_this() = 0;
404  std::shared_ptr<Channel> get_channel(struct sr_channel *ptr);
405 
406  struct sr_dev_inst *_structure;
407  std::map<struct sr_channel *, std::unique_ptr<Channel> > _channels;
408 private:
409  std::map<std::string, std::unique_ptr<ChannelGroup> > _channel_groups;
410 
411  friend class Session;
412  friend class Channel;
413  friend class ChannelGroup;
414  friend class Output;
415  friend class Analog;
416  friend struct std::default_delete<Device>;
417 };
418 
419 /** A real hardware device, connected via a driver */
420 class SR_API HardwareDevice :
421  public UserOwned<HardwareDevice>,
422  public Device
423 {
424 public:
425  /** Driver providing this device. */
426  std::shared_ptr<Driver> driver();
427 private:
428  HardwareDevice(std::shared_ptr<Driver> driver, struct sr_dev_inst *structure);
429  ~HardwareDevice();
430  std::shared_ptr<Device> get_shared_from_this();
431  std::shared_ptr<Driver> _driver;
432 
433  friend class Driver;
434  friend class ChannelGroup;
435  friend struct std::default_delete<HardwareDevice>;
436 };
437 
438 /** A virtual device, created by the user */
439 class SR_API UserDevice :
440  public UserOwned<UserDevice>,
441  public Device
442 {
443 public:
444  /** Add a new channel to this device. */
445  std::shared_ptr<Channel> add_channel(unsigned int index, const ChannelType *type, std::string name);
446 private:
447  UserDevice(std::string vendor, std::string model, std::string version);
448  ~UserDevice();
449  std::shared_ptr<Device> get_shared_from_this();
450 
451  friend class Context;
452  friend struct std::default_delete<UserDevice>;
453 };
454 
455 /** A channel on a device */
456 class SR_API Channel :
457  public ParentOwned<Channel, Device>
458 {
459 public:
460  /** Current name of this channel. */
461  std::string name() const;
462  /** Set the name of this channel. *
463  * @param name Name string to set. */
464  void set_name(std::string name);
465  /** Type of this channel. */
466  const ChannelType *type() const;
467  /** Enabled status of this channel. */
468  bool enabled() const;
469  /** Set the enabled status of this channel.
470  * @param value Boolean value to set. */
471  void set_enabled(bool value);
472  /** Get the index number of this channel. */
473  unsigned int index() const;
474 private:
475  explicit Channel(struct sr_channel *structure);
476  ~Channel();
477  struct sr_channel *_structure;
478  const ChannelType * const _type;
479  friend class Device;
480  friend class UserDevice;
481  friend class ChannelGroup;
482  friend class Session;
483  friend class TriggerStage;
484  friend class Context;
485  friend struct std::default_delete<Channel>;
486 };
487 
488 /** A group of channels on a device, which share some configuration */
489 class SR_API ChannelGroup :
490  public ParentOwned<ChannelGroup, Device>,
491  public Configurable
492 {
493 public:
494  /** Name of this channel group. */
495  std::string name() const;
496  /** List of the channels in this group. */
497  std::vector<std::shared_ptr<Channel> > channels();
498 private:
499  ChannelGroup(const Device *device, struct sr_channel_group *structure);
500  ~ChannelGroup();
501  std::vector<Channel *> _channels;
502  friend class Device;
503  friend struct std::default_delete<ChannelGroup>;
504 };
505 
506 /** A trigger configuration */
507 class SR_API Trigger : public UserOwned<Trigger>
508 {
509 public:
510  /** Name of this trigger configuration. */
511  std::string name() const;
512  /** List of the stages in this trigger. */
513  std::vector<std::shared_ptr<TriggerStage> > stages();
514  /** Add a new stage to this trigger. */
515  std::shared_ptr<TriggerStage> add_stage();
516 private:
517  Trigger(std::shared_ptr<Context> context, std::string name);
518  ~Trigger();
519  struct sr_trigger *_structure;
520  std::shared_ptr<Context> _context;
521  std::vector<std::unique_ptr<TriggerStage> > _stages;
522  friend class Context;
523  friend class Session;
524  friend struct std::default_delete<Trigger>;
525 };
526 
527 /** A stage in a trigger configuration */
528 class SR_API TriggerStage :
529  public ParentOwned<TriggerStage, Trigger>
530 {
531 public:
532  /** Index number of this stage. */
533  int number() const;
534  /** List of match conditions on this stage. */
535  std::vector<std::shared_ptr<TriggerMatch> > matches();
536  /** Add a new match condition to this stage.
537  * @param channel Channel to match on.
538  * @param type TriggerMatchType to apply. */
539  void add_match(std::shared_ptr<Channel> channel, const TriggerMatchType *type);
540  /** Add a new match condition to this stage.
541  * @param channel Channel to match on.
542  * @param type TriggerMatchType to apply.
543  * @param value Threshold value. */
544  void add_match(std::shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
545 private:
546  struct sr_trigger_stage *_structure;
547  std::vector<std::unique_ptr<TriggerMatch> > _matches;
548  explicit TriggerStage(struct sr_trigger_stage *structure);
549  ~TriggerStage();
550  friend class Trigger;
551  friend struct std::default_delete<TriggerStage>;
552 };
553 
554 /** A match condition in a trigger configuration */
555 class SR_API TriggerMatch :
556  public ParentOwned<TriggerMatch, TriggerStage>
557 {
558 public:
559  /** Channel this condition matches on. */
560  std::shared_ptr<Channel> channel();
561  /** Type of match. */
562  const TriggerMatchType *type() const;
563  /** Threshold value. */
564  float value() const;
565 private:
566  TriggerMatch(struct sr_trigger_match *structure, std::shared_ptr<Channel> channel);
567  ~TriggerMatch();
568  struct sr_trigger_match *_structure;
569  std::shared_ptr<Channel> _channel;
570  friend class TriggerStage;
571  friend struct std::default_delete<TriggerMatch>;
572 };
573 
574 /** Type of session stopped callback */
575 typedef std::function<void()> SessionStoppedCallback;
576 
577 /** Type of datafeed callback */
578 typedef std::function<void(std::shared_ptr<Device>, std::shared_ptr<Packet>)>
579  DatafeedCallbackFunction;
580 
581 /* Data required for C callback function to call a C++ datafeed callback */
582 class SR_PRIV DatafeedCallbackData
583 {
584 public:
585  void run(const struct sr_dev_inst *sdi,
586  const struct sr_datafeed_packet *pkt);
587 private:
588  DatafeedCallbackFunction _callback;
589  DatafeedCallbackData(Session *session,
590  DatafeedCallbackFunction callback);
591  Session *_session;
592  friend class Session;
593 };
594 
595 /** A virtual device associated with a stored session */
596 class SR_API SessionDevice :
597  public ParentOwned<SessionDevice, Session>,
598  public Device
599 {
600 private:
601  explicit SessionDevice(struct sr_dev_inst *sdi);
602  ~SessionDevice();
603  std::shared_ptr<Device> get_shared_from_this();
604 
605  friend class Session;
606  friend struct std::default_delete<SessionDevice>;
607 };
608 
609 /** A sigrok session */
610 class SR_API Session : public UserOwned<Session>
611 {
612 public:
613  /** Add a device to this session.
614  * @param device Device to add. */
615  void add_device(std::shared_ptr<Device> device);
616  /** List devices attached to this session. */
617  std::vector<std::shared_ptr<Device> > devices();
618  /** Remove all devices from this session. */
619  void remove_devices();
620  /** Add a datafeed callback to this session.
621  * @param callback Callback of the form callback(Device, Packet). */
622  void add_datafeed_callback(DatafeedCallbackFunction callback);
623  /** Remove all datafeed callbacks from this session. */
624  void remove_datafeed_callbacks();
625  /** Start the session. */
626  void start();
627  /** Run the session event loop. */
628  void run();
629  /** Stop the session. */
630  void stop();
631  /** Return whether the session is running. */
632  bool is_running() const;
633  /** Set callback to be invoked on session stop. */
634  void set_stopped_callback(SessionStoppedCallback callback);
635  /** Get current trigger setting. */
636  std::shared_ptr<Trigger> trigger();
637  /** Get the context. */
638  std::shared_ptr<Context> context();
639  /** Set trigger setting.
640  * @param trigger Trigger object to use. */
641  void set_trigger(std::shared_ptr<Trigger> trigger);
642  /** Get filename this session was loaded from. */
643  std::string filename() const;
644 private:
645  explicit Session(std::shared_ptr<Context> context);
646  Session(std::shared_ptr<Context> context, std::string filename);
647  ~Session();
648  std::shared_ptr<Device> get_device(const struct sr_dev_inst *sdi);
649  struct sr_session *_structure;
650  const std::shared_ptr<Context> _context;
651  std::map<const struct sr_dev_inst *, std::unique_ptr<SessionDevice> > _owned_devices;
652  std::map<const struct sr_dev_inst *, std::shared_ptr<Device> > _other_devices;
653  std::vector<std::unique_ptr<DatafeedCallbackData> > _datafeed_callbacks;
654  SessionStoppedCallback _stopped_callback;
655  std::string _filename;
656  std::shared_ptr<Trigger> _trigger;
657 
658  friend class Context;
659  friend class DatafeedCallbackData;
660  friend class SessionDevice;
661  friend struct std::default_delete<Session>;
662 };
663 
664 /** A packet on the session datafeed */
665 class SR_API Packet : public UserOwned<Packet>
666 {
667 public:
668  /** Type of this packet. */
669  const PacketType *type() const;
670  /** Payload of this packet. */
671  std::shared_ptr<PacketPayload> payload();
672 private:
673  Packet(std::shared_ptr<Device> device,
674  const struct sr_datafeed_packet *structure);
675  ~Packet();
676  const struct sr_datafeed_packet *_structure;
677  std::shared_ptr<Device> _device;
678  std::unique_ptr<PacketPayload> _payload;
679 
680  friend class Session;
681  friend class Output;
682  friend class DatafeedCallbackData;
683  friend class Header;
684  friend class Meta;
685  friend class Logic;
686  friend class Analog;
687  friend class Context;
688  friend struct std::default_delete<Packet>;
689 };
690 
691 /** Abstract base class for datafeed packet payloads */
692 class SR_API PacketPayload
693 {
694 protected:
695  PacketPayload();
696  virtual ~PacketPayload() = 0;
697 private:
698  virtual std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent) = 0;
699 
700  friend class Packet;
701  friend class Output;
702  friend struct std::default_delete<PacketPayload>;
703 };
704 
705 /** Payload of a datafeed header packet */
706 class SR_API Header :
707  public ParentOwned<Header, Packet>,
708  public PacketPayload
709 {
710 public:
711  /* Feed version number. */
712  int feed_version() const;
713  /* Start time of this session. */
714  Glib::DateTime start_time() const;
715 private:
716  explicit Header(const struct sr_datafeed_header *structure);
717  ~Header();
718  std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
719 
720  const struct sr_datafeed_header *_structure;
721 
722  friend class Packet;
723 };
724 
725 /** Payload of a datafeed metadata packet */
726 class SR_API Meta :
727  public ParentOwned<Meta, Packet>,
728  public PacketPayload
729 {
730 public:
731  /* Mapping of (ConfigKey, value) pairs. */
732  std::map<const ConfigKey *, Glib::VariantBase> config() const;
733 private:
734  explicit Meta(const struct sr_datafeed_meta *structure);
735  ~Meta();
736  std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
737 
738  const struct sr_datafeed_meta *_structure;
739  std::map<const ConfigKey *, Glib::VariantBase> _config;
740 
741  friend class Packet;
742 };
743 
744 /** Payload of a datafeed packet with logic data */
745 class SR_API Logic :
746  public ParentOwned<Logic, Packet>,
747  public PacketPayload
748 {
749 public:
750  /* Pointer to data. */
751  void *data_pointer();
752  /* Data length in bytes. */
753  size_t data_length() const;
754  /* Size of each sample in bytes. */
755  unsigned int unit_size() const;
756 private:
757  explicit Logic(const struct sr_datafeed_logic *structure);
758  ~Logic();
759  std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
760 
761  const struct sr_datafeed_logic *_structure;
762 
763  friend class Packet;
764  friend class Analog;
765  friend struct std::default_delete<Logic>;
766 };
767 
768 /** Payload of a datafeed packet with analog data */
769 class SR_API Analog :
770  public ParentOwned<Analog, Packet>,
771  public PacketPayload
772 {
773 public:
774  /** Pointer to data. */
775  void *data_pointer();
776  /**
777  * Fills dest pointer with the analog data converted to float.
778  * The pointer must have space for num_samples() floats.
779  */
780  void get_data_as_float(float *dest);
781  /** Number of samples in this packet. */
782  unsigned int num_samples() const;
783  /** Channels for which this packet contains data. */
784  std::vector<std::shared_ptr<Channel> > channels();
785  /** Size of a single sample in bytes. */
786  unsigned int unitsize() const;
787  /** Samples use a signed data type. */
788  bool is_signed() const;
789  /** Samples use float. */
790  bool is_float() const;
791  /** Samples are stored in big-endian order. */
792  bool is_bigendian() const;
793  /**
794  * Number of significant digits after the decimal point, if positive.
795  * When negative, exponent with reversed polarity that is necessary to
796  * express the value with all digits without a decimal point.
797  * Refers to the value we actually read on the wire.
798  *
799  * Examples:
800  *
801  * | On the wire | Exponential notation | Exp. not. (normalized) | digits |
802  * |-------------|----------------------|------------------------|--------|
803  * | 12.34 MOhm | 1.234 * 10^7 Ohm | 1234 * 10^4 Ohm | -4 |
804  * | 1.2345 MOhm | 1.2345 * 10^6 Ohm | 12345 * 10^2 Ohm | -2 |
805  * | 123.4 kOhm | 1.234 * 10^5 Ohm | 1234 * 10^2 Ohm | -2 |
806  * | 1234 Ohm | 1.234 * 10^3 Ohm | 1234 * 10^0 Ohm | 0 |
807  * | 12.34 Ohm | 1.234 * 10^1 Ohm | 1234 * 10^-2 Ohm | 2 |
808  * | 0.0123 Ohm | 1.23 * 10^-2 Ohm | 123 * 10^-4 Ohm | 4 |
809  * | 1.234 pF | 1.234 * 10^-12 F | 1234 * 10^-15 F | 15 |
810  */
811  int digits() const;
812  /** TBD */
813  bool is_digits_decimal() const;
814  /** TBD */
815  std::shared_ptr<Rational> scale();
816  /** TBD */
817  std::shared_ptr<Rational> offset();
818  /** Measured quantity of the samples in this packet. */
819  const Quantity *mq() const;
820  /** Unit of the samples in this packet. */
821  const Unit *unit() const;
822  /** Measurement flags associated with the samples in this packet. */
823  std::vector<const QuantityFlag *> mq_flags() const;
824  /**
825  * Provides a Logic packet that contains a conversion of the analog
826  * data using a simple threshold.
827  *
828  * @param threshold Threshold to use.
829  * @param data_ptr Pointer to num_samples() bytes where the logic
830  * samples are stored. When nullptr, memory for
831  * logic->data_pointer() will be allocated and must
832  * be freed by the caller.
833  */
834  std::shared_ptr<Logic> get_logic_via_threshold(float threshold,
835  uint8_t *data_ptr=nullptr) const;
836  /**
837  * Provides a Logic packet that contains a conversion of the analog
838  * data using a Schmitt-Trigger.
839  *
840  * @param lo_thr Low threshold to use (anything below this is low).
841  * @param hi_thr High threshold to use (anything above this is high).
842  * @param state Points to a byte that contains the current state of the
843  * converter. For best results, set to value of logic
844  * sample n-1.
845  * @param data_ptr Pointer to num_samples() bytes where the logic
846  * samples are stored. When nullptr, memory for
847  * logic->data_pointer() will be allocated and must be
848  * freed by the caller.
849  */
850  std::shared_ptr<Logic> get_logic_via_schmitt_trigger(float lo_thr,
851  float hi_thr, uint8_t *state, uint8_t *data_ptr=nullptr) const;
852 private:
853  explicit Analog(const struct sr_datafeed_analog *structure);
854  ~Analog();
855  std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
856 
857  const struct sr_datafeed_analog *_structure;
858 
859  friend class Packet;
860 };
861 
862 /** Number represented by a numerator/denominator integer pair */
863 class SR_API Rational :
864  public ParentOwned<Rational, Analog>
865 {
866 public:
867  /** Numerator, i.e. the dividend. */
868  int64_t numerator() const;
869  /** Denominator, i.e. the divider. */
870  uint64_t denominator() const;
871  /** Actual (lossy) value. */
872  float value() const;
873 private:
874  explicit Rational(const struct sr_rational *structure);
875  ~Rational();
876  std::shared_ptr<Rational> share_owned_by(std::shared_ptr<Analog> parent);
877 
878  const struct sr_rational *_structure;
879 
880  friend class Analog;
881  friend struct std::default_delete<Rational>;
882 };
883 
884 /** An input format supported by the library */
885 class SR_API InputFormat :
886  public ParentOwned<InputFormat, Context>
887 {
888 public:
889  /** Name of this input format. */
890  std::string name() const;
891  /** Description of this input format. */
892  std::string description() const;
893  /** A list of preferred file name extensions for this file format.
894  * @note This list is a recommendation only. */
895  std::vector<std::string> extensions() const;
896  /** Options supported by this input format. */
897  std::map<std::string, std::shared_ptr<Option> > options();
898  /** Create an input using this input format.
899  * @param options Mapping of (option name, value) pairs. */
900  std::shared_ptr<Input> create_input(std::map<std::string, Glib::VariantBase>
901  options = std::map<std::string, Glib::VariantBase>());
902 private:
903  explicit InputFormat(const struct sr_input_module *structure);
904  ~InputFormat();
905 
906  const struct sr_input_module *_structure;
907 
908  friend class Context;
909  friend class InputDevice;
910  friend struct std::default_delete<InputFormat>;
911 };
912 
913 /** An input instance (an input format applied to a file or stream) */
914 class SR_API Input : public UserOwned<Input>
915 {
916 public:
917  /** Virtual device associated with this input. */
918  std::shared_ptr<InputDevice> device();
919  /** Send next stream data.
920  * @param data Next stream data.
921  * @param length Length of data. */
922  void send(void *data, size_t length);
923  /** Signal end of input data. */
924  void end();
925  void reset();
926 private:
927  Input(std::shared_ptr<Context> context, const struct sr_input *structure);
928  ~Input();
929  const struct sr_input *_structure;
930  std::shared_ptr<Context> _context;
931  std::unique_ptr<InputDevice> _device;
932 
933  friend class Context;
934  friend class InputFormat;
935  friend struct std::default_delete<Input>;
936 };
937 
938 /** A virtual device associated with an input */
939 class SR_API InputDevice :
940  public ParentOwned<InputDevice, Input>,
941  public Device
942 {
943 private:
944  InputDevice(std::shared_ptr<Input> input, struct sr_dev_inst *sdi);
945  ~InputDevice();
946  std::shared_ptr<Device> get_shared_from_this();
947  std::shared_ptr<Input> _input;
948  friend class Input;
949  friend struct std::default_delete<InputDevice>;
950 };
951 
952 /** An option used by an output format */
953 class SR_API Option : public UserOwned<Option>
954 {
955 public:
956  /** Short name of this option suitable for command line usage. */
957  std::string id() const;
958  /** Short name of this option suitable for GUI usage. */
959  std::string name() const;
960  /** Description of this option in a sentence. */
961  std::string description() const;
962  /** Default value for this option. */
963  Glib::VariantBase default_value() const;
964  /** Possible values for this option, if a limited set. */
965  std::vector<Glib::VariantBase> values() const;
966  /** Parse a string argument into the appropriate type for this option. */
967  Glib::VariantBase parse_string(std::string value);
968 private:
969  Option(const struct sr_option *structure,
970  std::shared_ptr<const struct sr_option *> structure_array);
971  ~Option();
972  const struct sr_option *_structure;
973  std::shared_ptr<const struct sr_option *> _structure_array;
974 
975  friend class InputFormat;
976  friend class OutputFormat;
977  friend struct std::default_delete<Option>;
978 };
979 
980 /** An output format supported by the library */
981 class SR_API OutputFormat :
982  public ParentOwned<OutputFormat, Context>
983 {
984 public:
985  /** Name of this output format. */
986  std::string name() const;
987  /** Description of this output format. */
988  std::string description() const;
989  /** A list of preferred file name extensions for this file format.
990  * @note This list is a recommendation only. */
991  std::vector<std::string> extensions() const;
992  /** Options supported by this output format. */
993  std::map<std::string, std::shared_ptr<Option> > options();
994  /** Create an output using this format.
995  * @param device Device to output for.
996  * @param options Mapping of (option name, value) pairs. */
997  std::shared_ptr<Output> create_output(std::shared_ptr<Device> device,
998  std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
999  /** Create an output using this format.
1000  * @param filename Name of destination file.
1001  * @param device Device to output for.
1002  * @param options Mapping of (option name, value) pairs. */
1003  std::shared_ptr<Output> create_output(std::string filename,
1004  std::shared_ptr<Device> device,
1005  std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
1006  /**
1007  * Checks whether a given flag is set.
1008  * @param flag Flag to check
1009  * @return true if flag is set for this module
1010  * @see sr_output_flags
1011  */
1012  bool test_flag(const OutputFlag *flag) const;
1013 private:
1014  explicit OutputFormat(const struct sr_output_module *structure);
1015  ~OutputFormat();
1016 
1017  const struct sr_output_module *_structure;
1018 
1019  friend class Context;
1020  friend class Output;
1021  friend struct std::default_delete<OutputFormat>;
1022 };
1023 
1024 /** An output instance (an output format applied to a device) */
1025 class SR_API Output : public UserOwned<Output>
1026 {
1027 public:
1028  /** Update output with data from the given packet.
1029  * @param packet Packet to handle. */
1030  std::string receive(std::shared_ptr<Packet> packet);
1031  /** Output format in use for this output */
1032  std::shared_ptr<OutputFormat> format();
1033 private:
1034  Output(std::shared_ptr<OutputFormat> format, std::shared_ptr<Device> device);
1035  Output(std::shared_ptr<OutputFormat> format,
1036  std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
1037  Output(std::string filename, std::shared_ptr<OutputFormat> format,
1038  std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
1039  ~Output();
1040 
1041  const struct sr_output *_structure;
1042  const std::shared_ptr<OutputFormat> _format;
1043  const std::shared_ptr<Device> _device;
1044  const std::map<std::string, Glib::VariantBase> _options;
1045 
1046  friend class OutputFormat;
1047  friend struct std::default_delete<Output>;
1048 };
1049 
1050 /** Base class for objects which wrap an enumeration value from libsigrok */
1051 template <class Class, typename Enum> class SR_API EnumValue
1052 {
1053 public:
1054  /** The integer constant associated with this value. */
1055  int id() const
1056  {
1057  return static_cast<int>(_id);
1058  }
1059  /** The name associated with this value. */
1060  std::string name() const
1061  {
1062  return _name;
1063  }
1064  /** Get value associated with a given integer constant. */
1065  static const Class *get(int id)
1066  {
1067  const auto pos = _values.find(static_cast<Enum>(id));
1068  if (pos == _values.end())
1069  throw Error(SR_ERR_ARG);
1070  return pos->second;
1071  }
1072  /** Get possible values. */
1073  static std::vector<const Class *> values()
1074  {
1075  std::vector<const Class *> result;
1076  for (auto entry : _values)
1077  result.push_back(entry.second);
1078  return result;
1079  }
1080 protected:
1081  EnumValue(Enum id, const char name[]) : _id(id), _name(name)
1082  {
1083  }
1084  ~EnumValue()
1085  {
1086  }
1087 private:
1088  static const std::map<const Enum, const Class * const> _values;
1089  const Enum _id;
1090  const std::string _name;
1091 };
1092 
1093 }
1094 
1095 #include <libsigrokcxx/enums.hpp>
1096 
1097 #endif
An output instance (an output format applied to a device)
Payload of a datafeed metadata packet.
A stage in a trigger configuration.
A packet on the session datafeed.
A real hardware device, connected via a driver.
static std::vector< const Class * > values()
Get possible values.
Configuration capability.
Definition: enums.hpp:504
Measured quantity.
Definition: enums.hpp:112
A virtual device associated with a stored session.
An option used by an output format.
Log verbosity level.
Definition: enums.hpp:7
A virtual device associated with an input.
A virtual device, created by the user.
Channel type.
Definition: enums.hpp:485
Trigger match type.
Definition: enums.hpp:442
The global libsigrok context.
An output format supported by the library.
Exception thrown when an error code is returned by any libsigrok call.
A hardware driver provided by the library.
int id() const
The integer constant associated with this value.
Type of datafeed packet.
Definition: enums.hpp:75
An input instance (an input format applied to a file or stream)
A sigrok session.
A group of channels on a device, which share some configuration.
Number represented by a numerator/denominator integer pair.
Payload of a datafeed packet with logic data.
A match condition in a trigger configuration.
Flag applied to output modules.
Definition: enums.hpp:469
Base class for objects which wrap an enumeration value from libsigrok.
Unit of measurement.
Definition: enums.hpp:222
A generic device, either hardware or virtual.
Resource reader delegate.
An object that can be configured.
std::string name() const
The name associated with this value.
Abstract base class for datafeed packet payloads.
Payload of a datafeed header packet.
A channel on a device.
Payload of a datafeed packet with analog data.
An input format supported by the library.
A trigger configuration.
Configuration key.
Definition: enums.hpp:526