]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / bindings / cxx / include / libsigrokcxx / 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