]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp
korad-kaxxxxp: use ID text prefix with optional version for RND models
[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::TimeVal 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::TimeVal 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          * or number of non-significant digits before the decimal point if negative
796          * (refers to the value we actually read on the wire).
797          */
798         int digits() const;
799         /** TBD */
800         bool is_digits_decimal() const;
801         /** TBD */
802         std::shared_ptr<Rational> scale();
803         /** TBD */
804         std::shared_ptr<Rational> offset();
805         /** Measured quantity of the samples in this packet. */
806         const Quantity *mq() const;
807         /** Unit of the samples in this packet. */
808         const Unit *unit() const;
809         /** Measurement flags associated with the samples in this packet. */
810         std::vector<const QuantityFlag *> mq_flags() const;
811         /**
812          * Provides a Logic packet that contains a conversion of the analog
813          * data using a simple threshold.
814          *
815          * @param threshold Threshold to use.
816          * @param data_ptr Pointer to num_samples() bytes where the logic
817          *                 samples are stored. When nullptr, memory for
818          *                 logic->data_pointer() will be allocated and must
819          *                 be freed by the caller.
820          */
821         std::shared_ptr<Logic> get_logic_via_threshold(float threshold,
822                 uint8_t *data_ptr=nullptr) const;
823         /**
824          * Provides a Logic packet that contains a conversion of the analog
825          * data using a Schmitt-Trigger.
826          *
827          * @param lo_thr Low threshold to use (anything below this is low).
828          * @param hi_thr High threshold to use (anything above this is high).
829          * @param state Points to a byte that contains the current state of the
830          *              converter. For best results, set to value of logic
831          *              sample n-1.
832          * @param data_ptr Pointer to num_samples() bytes where the logic
833          *                 samples are stored. When nullptr, memory for
834          *                 logic->data_pointer() will be allocated and must be
835          *                 freed by the caller.
836          */
837         std::shared_ptr<Logic> get_logic_via_schmitt_trigger(float lo_thr,
838                 float hi_thr, uint8_t *state, uint8_t *data_ptr=nullptr) const;
839 private:
840         explicit Analog(const struct sr_datafeed_analog *structure);
841         ~Analog();
842         std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
843
844         const struct sr_datafeed_analog *_structure;
845
846         friend class Packet;
847 };
848
849 /** Number represented by a numerator/denominator integer pair */
850 class SR_API Rational :
851         public ParentOwned<Rational, Analog>
852 {
853 public:
854         /** Numerator, i.e. the dividend. */
855         int64_t numerator() const;
856         /** Denominator, i.e. the divider. */
857         uint64_t denominator() const;
858         /** Actual (lossy) value. */
859         float value() const;
860 private:
861         explicit Rational(const struct sr_rational *structure);
862         ~Rational();
863         std::shared_ptr<Rational> share_owned_by(std::shared_ptr<Analog> parent);
864
865         const struct sr_rational *_structure;
866
867         friend class Analog;
868         friend struct std::default_delete<Rational>;
869 };
870
871 /** An input format supported by the library */
872 class SR_API InputFormat :
873         public ParentOwned<InputFormat, Context>
874 {
875 public:
876         /** Name of this input format. */
877         std::string name() const;
878         /** Description of this input format. */
879         std::string description() const;
880         /** A list of preferred file name extensions for this file format.
881          * @note This list is a recommendation only. */
882         std::vector<std::string> extensions() const;
883         /** Options supported by this input format. */
884         std::map<std::string, std::shared_ptr<Option> > options();
885         /** Create an input using this input format.
886          * @param options Mapping of (option name, value) pairs. */
887         std::shared_ptr<Input> create_input(std::map<std::string, Glib::VariantBase>
888                         options = std::map<std::string, Glib::VariantBase>());
889 private:
890         explicit InputFormat(const struct sr_input_module *structure);
891         ~InputFormat();
892
893         const struct sr_input_module *_structure;
894
895         friend class Context;
896         friend class InputDevice;
897         friend struct std::default_delete<InputFormat>;
898 };
899
900 /** An input instance (an input format applied to a file or stream) */
901 class SR_API Input : public UserOwned<Input>
902 {
903 public:
904         /** Virtual device associated with this input. */
905         std::shared_ptr<InputDevice> device();
906         /** Send next stream data.
907          * @param data Next stream data.
908          * @param length Length of data. */
909         void send(void *data, size_t length);
910         /** Signal end of input data. */
911         void end();
912         void reset();
913 private:
914         Input(std::shared_ptr<Context> context, const struct sr_input *structure);
915         ~Input();
916         const struct sr_input *_structure;
917         std::shared_ptr<Context> _context;
918         std::unique_ptr<InputDevice> _device;
919
920         friend class Context;
921         friend class InputFormat;
922         friend struct std::default_delete<Input>;
923 };
924
925 /** A virtual device associated with an input */
926 class SR_API InputDevice :
927         public ParentOwned<InputDevice, Input>,
928         public Device
929 {
930 private:
931         InputDevice(std::shared_ptr<Input> input, struct sr_dev_inst *sdi);
932         ~InputDevice();
933         std::shared_ptr<Device> get_shared_from_this();
934         std::shared_ptr<Input> _input;
935         friend class Input;
936         friend struct std::default_delete<InputDevice>;
937 };
938
939 /** An option used by an output format */
940 class SR_API Option : public UserOwned<Option>
941 {
942 public:
943         /** Short name of this option suitable for command line usage. */
944         std::string id() const;
945         /** Short name of this option suitable for GUI usage. */
946         std::string name() const;
947         /** Description of this option in a sentence. */
948         std::string description() const;
949         /** Default value for this option. */
950         Glib::VariantBase default_value() const;
951         /** Possible values for this option, if a limited set. */
952         std::vector<Glib::VariantBase> values() const;
953         /** Parse a string argument into the appropriate type for this option. */
954         Glib::VariantBase parse_string(std::string value);
955 private:
956         Option(const struct sr_option *structure,
957                 std::shared_ptr<const struct sr_option *> structure_array);
958         ~Option();
959         const struct sr_option *_structure;
960         std::shared_ptr<const struct sr_option *> _structure_array;
961
962         friend class InputFormat;
963         friend class OutputFormat;
964         friend struct std::default_delete<Option>;
965 };
966
967 /** An output format supported by the library */
968 class SR_API OutputFormat :
969         public ParentOwned<OutputFormat, Context>
970 {
971 public:
972         /** Name of this output format. */
973         std::string name() const;
974         /** Description of this output format. */
975         std::string description() const;
976         /** A list of preferred file name extensions for this file format.
977          * @note This list is a recommendation only. */
978         std::vector<std::string> extensions() const;
979         /** Options supported by this output format. */
980         std::map<std::string, std::shared_ptr<Option> > options();
981         /** Create an output using this format.
982          * @param device Device to output for.
983          * @param options Mapping of (option name, value) pairs. */
984         std::shared_ptr<Output> create_output(std::shared_ptr<Device> device,
985                 std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
986         /** Create an output using this format.
987          * @param filename Name of destination file.
988          * @param device Device to output for.
989          * @param options Mapping of (option name, value) pairs. */
990         std::shared_ptr<Output> create_output(std::string filename,
991                 std::shared_ptr<Device> device,
992                 std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
993         /**
994          * Checks whether a given flag is set.
995          * @param flag Flag to check
996          * @return true if flag is set for this module
997          * @see sr_output_flags
998          */
999         bool test_flag(const OutputFlag *flag) const;
1000 private:
1001         explicit OutputFormat(const struct sr_output_module *structure);
1002         ~OutputFormat();
1003
1004         const struct sr_output_module *_structure;
1005
1006         friend class Context;
1007         friend class Output;
1008         friend struct std::default_delete<OutputFormat>;
1009 };
1010
1011 /** An output instance (an output format applied to a device) */
1012 class SR_API Output : public UserOwned<Output>
1013 {
1014 public:
1015         /** Update output with data from the given packet.
1016          * @param packet Packet to handle. */
1017         std::string receive(std::shared_ptr<Packet> packet);
1018         /** Output format in use for this output */
1019         std::shared_ptr<OutputFormat> format();
1020 private:
1021         Output(std::shared_ptr<OutputFormat> format, std::shared_ptr<Device> device);
1022         Output(std::shared_ptr<OutputFormat> format,
1023                 std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
1024         Output(std::string filename, std::shared_ptr<OutputFormat> format,
1025                 std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
1026         ~Output();
1027
1028         const struct sr_output *_structure;
1029         const std::shared_ptr<OutputFormat> _format;
1030         const std::shared_ptr<Device> _device;
1031         const std::map<std::string, Glib::VariantBase> _options;
1032
1033         friend class OutputFormat;
1034         friend struct std::default_delete<Output>;
1035 };
1036
1037 /** Base class for objects which wrap an enumeration value from libsigrok */
1038 template <class Class, typename Enum> class SR_API EnumValue
1039 {
1040 public:
1041         /** The integer constant associated with this value. */
1042         int id() const
1043         {
1044                 return static_cast<int>(_id);
1045         }
1046         /** The name associated with this value. */
1047         std::string name() const
1048         {
1049                 return _name;
1050         }
1051         /** Get value associated with a given integer constant. */
1052         static const Class *get(int id)
1053         {
1054                 const auto pos = _values.find(static_cast<Enum>(id));
1055                 if (pos == _values.end())
1056                         throw Error(SR_ERR_ARG);
1057                 return pos->second;
1058         }
1059         /** Get possible values. */
1060         static std::vector<const Class *> values()
1061         {
1062                 std::vector<const Class *> result;
1063                 for (auto entry : _values)
1064                         result.push_back(entry.second);
1065                 return result;
1066         }
1067 protected:
1068         EnumValue(Enum id, const char name[]) : _id(id), _name(name)
1069         {
1070         }
1071         ~EnumValue()
1072         {
1073         }
1074 private:
1075         static const std::map<const Enum, const Class * const> _values;
1076         const Enum _id;
1077         const std::string _name;
1078 };
1079
1080 }
1081
1082 #include <libsigrokcxx/enums.hpp>
1083
1084 #endif