]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp
38b71a6d10c75cfe0d303f49a974456139e6d22d
[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 #include <glibmm.h>
75
76 #include <stdexcept>
77 #include <memory>
78 #include <vector>
79 #include <map>
80 #include <set>
81
82 namespace sigrok
83 {
84
85 using namespace std;
86
87 /* Forward declarations */
88 class SR_API Error;
89 class SR_API Context;
90 class SR_API Driver;
91 class SR_API Device;
92 class SR_API HardwareDevice;
93 class SR_API Channel;
94 class SR_API Session;
95 class SR_API ConfigKey;
96 class SR_API InputFormat;
97 class SR_API OutputFormat;
98 class SR_API OutputFlag;
99 class SR_API LogLevel;
100 class SR_API ChannelGroup;
101 class SR_API Trigger;
102 class SR_API TriggerStage;
103 class SR_API TriggerMatch;
104 class SR_API TriggerMatchType;
105 class SR_API ChannelType;
106 class SR_API Packet;
107 class SR_API PacketPayload;
108 class SR_API PacketType;
109 class SR_API Quantity;
110 class SR_API Unit;
111 class SR_API QuantityFlag;
112 class SR_API Input;
113 class SR_API InputDevice;
114 class SR_API Output;
115 class SR_API DataType;
116 class SR_API Option;
117 class SR_API UserDevice;
118
119 /** Exception thrown when an error code is returned by any libsigrok call. */
120 class SR_API Error: public exception
121 {
122 public:
123         explicit Error(int result);
124         ~Error() noexcept;
125         const int result;
126         const char *what() const noexcept;
127 };
128
129 /* Base template for classes whose resources are owned by a parent object. */
130 template <class Class, class Parent, typename Struct>
131 class SR_API ParentOwned
132 {
133 private:
134         /* Weak pointer for shared_from_this() implementation. */
135         weak_ptr<Class> _weak_this;
136
137         static void reset_parent(Class *object)
138         {
139                 if (!object->_parent)
140                         throw Error(SR_ERR_BUG);
141                 object->_parent.reset();
142         }
143
144 protected:
145         /*  Parent object which owns this child object's underlying structure.
146
147                 This shared pointer will be null when this child is unused, but
148                 will be assigned to point to the parent before any shared pointer
149                 to this child is handed out to the user.
150
151                 When the reference count of this child falls to zero, this shared
152                 pointer to its parent is reset by a custom deleter on the child's
153                 shared pointer.
154
155                 This strategy ensures that the destructors for both the child and
156                 the parent are called at the correct time, i.e. only when all
157                 references to both the parent and all its children are gone. */
158         shared_ptr<Parent> _parent;
159
160         Struct *_structure;
161
162         explicit ParentOwned(Struct *structure) :
163                 _structure(structure)
164         {
165         }
166
167         /* Note, this implementation will create a new smart_ptr if none exists. */
168         shared_ptr<Class> shared_from_this()
169         {
170                 shared_ptr<Class> shared = _weak_this.lock();
171
172                 if (!shared)
173                 {
174                         shared.reset(static_cast<Class *>(this), &reset_parent);
175                         _weak_this = shared;
176                 }
177
178                 return shared;
179         }
180
181         shared_ptr<Class> get_shared_pointer(shared_ptr<Parent> parent)
182         {
183                 if (!parent)
184                         throw Error(SR_ERR_BUG);
185                 this->_parent = parent;
186                 return shared_from_this();
187         }
188
189 public:
190         /* Get parent object that owns this object. */
191         shared_ptr<Parent> parent()
192         {
193                 return _parent;
194         }
195 };
196
197 /* Base template for classes whose resources are owned by the user. */
198 template <class Class, typename Struct>
199 class SR_API UserOwned : public enable_shared_from_this<Class>
200 {
201 protected:
202         Struct *_structure;
203
204         explicit UserOwned(Struct *structure) :
205                 _structure(structure)
206         {
207         }
208
209         shared_ptr<Class> shared_from_this()
210         {
211                 auto shared = enable_shared_from_this<Class>::shared_from_this();
212                 if (!shared)
213                         throw Error(SR_ERR_BUG);
214                 return shared;
215         }
216
217         /* Deleter needed to allow shared_ptr use with protected destructor. */
218         class Deleter
219         {
220         public:
221                 void operator()(Class *object) { delete object; }
222         };
223 };
224
225 /** Type of log callback */
226 typedef function<void(const LogLevel *, string message)> LogCallbackFunction;
227
228 /** Resource reader delegate. */
229 class SR_API ResourceReader
230 {
231 public:
232         ResourceReader() {}
233         virtual ~ResourceReader();
234 private:
235         /** Resource open hook. */
236         virtual void open(struct sr_resource *res, string name) = 0;
237         /** Resource close hook. */
238         virtual void close(struct sr_resource *res) = 0;
239         /** Resource read hook. */
240         virtual size_t read(const struct sr_resource *res, void *buf, size_t count) = 0;
241
242         static SR_PRIV int open_callback(struct sr_resource *res,
243                         const char *name, void *cb_data) noexcept;
244         static SR_PRIV int close_callback(struct sr_resource *res,
245                         void *cb_data) noexcept;
246         static SR_PRIV ssize_t read_callback(const struct sr_resource *res,
247                         void *buf, size_t count, void *cb_data) noexcept;
248         friend class Context;
249 };
250
251 /** The global libsigrok context */
252 class SR_API Context : public UserOwned<Context, struct sr_context>
253 {
254 public:
255         /** Create new context */
256         static shared_ptr<Context> create();
257         /** libsigrok package version. */
258         static string package_version();
259         /** libsigrok library version. */
260         static string lib_version();
261         /** Available hardware drivers, indexed by name. */
262         map<string, shared_ptr<Driver> > drivers();
263         /** Available input formats, indexed by name. */
264         map<string, shared_ptr<InputFormat> > input_formats();
265         /** Available output formats, indexed by name. */
266         map<string, shared_ptr<OutputFormat> > output_formats();
267         /** Current log level. */
268         const LogLevel *log_level() const;
269         /** Set the log level.
270          * @param level LogLevel to use. */
271         void set_log_level(const LogLevel *level);
272         /** Set the log callback.
273          * @param callback Callback of the form callback(LogLevel, string). */
274         void set_log_callback(LogCallbackFunction callback);
275         /** Set the log callback to the default handler. */
276         void set_log_callback_default();
277         /** Install a delegate for reading resource files.
278          * @param reader The resource reader delegate, or nullptr to unset. */
279         void set_resource_reader(ResourceReader *reader);
280         /** Create a new session. */
281         shared_ptr<Session> create_session();
282         /** Create a new user device. */
283         shared_ptr<UserDevice> create_user_device(
284                 string vendor, string model, string version);
285         /** Create a header packet. */
286         shared_ptr<Packet> create_header_packet(Glib::TimeVal start_time);
287         /** Create a meta packet. */
288         shared_ptr<Packet> create_meta_packet(
289                 const map<const ConfigKey *, Glib::VariantBase> &config);
290         /** Create a logic packet. */
291         shared_ptr<Packet> create_logic_packet(
292                 void *data_pointer, size_t data_length, unsigned int unit_size);
293         /** Create an analog packet. */
294         shared_ptr<Packet> create_analog_packet(
295                 const vector<shared_ptr<Channel> > &channels,
296                 float *data_pointer, unsigned int num_samples, const Quantity *mq,
297                 const Unit *unit, const vector<const QuantityFlag *> &mqflags);
298         /** Load a saved session.
299          * @param filename File name string. */
300         shared_ptr<Session> load_session(string filename);
301         /** Create a new trigger.
302          * @param name Name string for new trigger. */
303         shared_ptr<Trigger> create_trigger(string name);
304         /** Open an input file.
305          * @param filename File name string. */
306         shared_ptr<Input> open_file(string filename);
307         /** Open an input stream based on header data.
308          * @param header Initial data from stream. */
309         shared_ptr<Input> open_stream(string header);
310         map<string, string> serials(shared_ptr<Driver> driver) const;
311 private:
312         map<string, Driver *> _drivers;
313         map<string, InputFormat *> _input_formats;
314         map<string, OutputFormat *> _output_formats;
315         Session *_session;
316         LogCallbackFunction _log_callback;
317         Context();
318         ~Context();
319         friend class Deleter;
320         friend class Session;
321         friend class Driver;
322 };
323
324 enum Capability {
325         GET = SR_CONF_GET,
326         SET = SR_CONF_SET,
327         LIST = SR_CONF_LIST
328 };
329
330 /** An object that can be configured. */
331 class SR_API Configurable
332 {
333 public:
334         /** Read configuration for the given key.
335          * @param key ConfigKey to read. */
336         Glib::VariantBase config_get(const ConfigKey *key) const;
337         /** Set configuration for the given key to a specified value.
338          * @param key ConfigKey to set.
339          * @param value Value to set. */
340         void config_set(const ConfigKey *key, const Glib::VariantBase &value);
341         /** Enumerate available values for the given configuration key.
342          * @param key ConfigKey to enumerate values for. */
343         Glib::VariantContainerBase config_list(const ConfigKey *key) const;
344         /** Enumerate available keys, according to a given index key. */
345         map<const ConfigKey *, set<Capability> > config_keys(const ConfigKey *key);
346         /** Check for a key in the list from a given index key. */
347         bool config_check(const ConfigKey *key, const ConfigKey *index_key) const;
348 protected:
349         Configurable(
350                 struct sr_dev_driver *driver,
351                 struct sr_dev_inst *sdi,
352                 struct sr_channel_group *channel_group);
353         virtual ~Configurable();
354         struct sr_dev_driver *config_driver;
355         struct sr_dev_inst *config_sdi;
356         struct sr_channel_group *config_channel_group;
357 };
358
359 /** A hardware driver provided by the library */
360 class SR_API Driver :
361         public ParentOwned<Driver, Context, struct sr_dev_driver>,
362         public Configurable
363 {
364 public:
365         /** Name of this driver. */
366         string name() const;
367         /** Long name for this driver. */
368         string long_name() const;
369         /** Scan for devices and return a list of devices found.
370          * @param options Mapping of (ConfigKey, value) pairs. */
371         vector<shared_ptr<HardwareDevice> > scan(
372                 const map<const ConfigKey *, Glib::VariantBase> &options = {});
373 private:
374         bool _initialized;
375         vector<HardwareDevice *> _devices;
376         explicit Driver(struct sr_dev_driver *structure);
377         ~Driver();
378         friend class Context;
379         friend class HardwareDevice;
380         friend class ChannelGroup;
381 };
382
383 /** A generic device, either hardware or virtual */
384 class SR_API Device : public Configurable
385 {
386 public:
387         /** Vendor name for this device. */
388         string vendor() const;
389         /** Model name for this device. */
390         string model() const;
391         /** Version string for this device. */
392         string version() const;
393         /** Serial number for this device. */
394         string serial_number() const;
395         /** Connection ID for this device. */
396         string connection_id() const;
397         /** List of the channels available on this device. */
398         vector<shared_ptr<Channel> > channels();
399         /** Channel groups available on this device, indexed by name. */
400         map<string, shared_ptr<ChannelGroup> > channel_groups();
401         /** Open device. */
402         void open();
403         /** Close device. */
404         void close();
405 protected:
406         explicit Device(struct sr_dev_inst *structure);
407         ~Device();
408         virtual shared_ptr<Device> get_shared_from_this() = 0;
409         shared_ptr<Channel> get_channel(struct sr_channel *ptr);
410
411         struct sr_dev_inst *_structure;
412         map<struct sr_channel *, Channel *> _channels;
413 private:
414         map<string, ChannelGroup *> _channel_groups;
415         /** Deleter needed to allow shared_ptr use with protected destructor. */
416         class Deleter
417         {
418         public:
419                 void operator()(Device *device) { delete device; }
420         };
421         friend class Deleter;
422         friend class Session;
423         friend class Channel;
424         friend class ChannelGroup;
425         friend class Output;
426         friend class Analog;
427 };
428
429 /** A real hardware device, connected via a driver */
430 class SR_API HardwareDevice :
431         public UserOwned<HardwareDevice, struct sr_dev_inst>,
432         public Device
433 {
434 public:
435         /** Driver providing this device. */
436         shared_ptr<Driver> driver();
437 private:
438         HardwareDevice(shared_ptr<Driver> driver, struct sr_dev_inst *structure);
439         ~HardwareDevice();
440         shared_ptr<Device> get_shared_from_this();
441         shared_ptr<Driver> _driver;
442         /** Deleter needed to allow shared_ptr use with protected destructor. */
443         class Deleter
444         {
445         public:
446                 void operator()(HardwareDevice *device) { delete device; }
447         };
448         friend class Deleter;
449         friend class Driver;
450         friend class ChannelGroup;
451 };
452
453 /** A virtual device, created by the user */
454 class SR_API UserDevice :
455         public UserOwned<UserDevice, struct sr_dev_inst>,
456         public Device
457 {
458 public:
459         /** Add a new channel to this device. */
460         shared_ptr<Channel> add_channel(unsigned int index, const ChannelType *type, string name);
461 private:
462         UserDevice(string vendor, string model, string version);
463         ~UserDevice();
464         shared_ptr<Device> get_shared_from_this();
465         /** Deleter needed to allow shared_ptr use with protected destructor. */
466         class Deleter
467         {
468         public:
469                 void operator()(UserDevice *device) { delete device; }
470         };
471         friend class Context;
472         friend class Deleter;
473 };
474
475 /** A channel on a device */
476 class SR_API Channel :
477         public ParentOwned<Channel, Device, struct sr_channel>
478 {
479 public:
480         /** Current name of this channel. */
481         string name() const;
482         /** Set the name of this channel. *
483          * @param name Name string to set. */
484         void set_name(string name);
485         /** Type of this channel. */
486         const ChannelType *type() const;
487         /** Enabled status of this channel. */
488         bool enabled() const;
489         /** Set the enabled status of this channel.
490          * @param value Boolean value to set. */
491         void set_enabled(bool value);
492         /** Get the index number of this channel. */
493         unsigned int index() const;
494 private:
495         explicit Channel(struct sr_channel *structure);
496         ~Channel();
497         const ChannelType * const _type;
498         friend class Device;
499         friend class UserDevice;
500         friend class ChannelGroup;
501         friend class Session;
502         friend class TriggerStage;
503         friend class Context;
504 };
505
506 /** A group of channels on a device, which share some configuration */
507 class SR_API ChannelGroup :
508         public ParentOwned<ChannelGroup, Device, struct sr_channel_group>,
509         public Configurable
510 {
511 public:
512         /** Name of this channel group. */
513         string name() const;
514         /** List of the channels in this group. */
515         vector<shared_ptr<Channel> > channels();
516 private:
517         ChannelGroup(Device *device, struct sr_channel_group *structure);
518         ~ChannelGroup();
519         vector<Channel *> _channels;
520         friend class Device;
521 };
522
523 /** A trigger configuration */
524 class SR_API Trigger : public UserOwned<Trigger, struct sr_trigger>
525 {
526 public:
527         /** Name of this trigger configuration. */
528         string name() const;
529         /** List of the stages in this trigger. */
530         vector<shared_ptr<TriggerStage> > stages();
531         /** Add a new stage to this trigger. */
532         shared_ptr<TriggerStage> add_stage();
533 private:
534         Trigger(shared_ptr<Context> context, string name);
535         ~Trigger();
536         shared_ptr<Context> _context;
537         vector<TriggerStage *> _stages;
538         friend class Deleter;
539         friend class Context;
540         friend class Session;
541 };
542
543 /** A stage in a trigger configuration */
544 class SR_API TriggerStage :
545         public ParentOwned<TriggerStage, Trigger, struct sr_trigger_stage>
546 {
547 public:
548         /** Index number of this stage. */
549         int number() const;
550         /** List of match conditions on this stage. */
551         vector<shared_ptr<TriggerMatch> > matches();
552         /** Add a new match condition to this stage.
553          * @param channel Channel to match on.
554          * @param type TriggerMatchType to apply. */
555         void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type);
556         /** Add a new match condition to this stage.
557          * @param channel Channel to match on.
558          * @param type TriggerMatchType to apply.
559          * @param value Threshold value. */
560         void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
561 private:
562         vector<TriggerMatch *> _matches;
563         explicit TriggerStage(struct sr_trigger_stage *structure);
564         ~TriggerStage();
565         friend class Trigger;
566 };
567
568 /** A match condition in a trigger configuration  */
569 class SR_API TriggerMatch :
570         public ParentOwned<TriggerMatch, TriggerStage, struct sr_trigger_match>
571 {
572 public:
573         /** Channel this condition matches on. */
574         shared_ptr<Channel> channel();
575         /** Type of match. */
576         const TriggerMatchType *type() const;
577         /** Threshold value. */
578         float value() const;
579 private:
580         TriggerMatch(struct sr_trigger_match *structure, shared_ptr<Channel> channel);
581         ~TriggerMatch();
582         shared_ptr<Channel> _channel;
583         friend class TriggerStage;
584 };
585
586 /** Type of session stopped callback */
587 typedef function<void()> SessionStoppedCallback;
588
589 /** Type of datafeed callback */
590 typedef function<void(shared_ptr<Device>, shared_ptr<Packet>)>
591         DatafeedCallbackFunction;
592
593 /* Data required for C callback function to call a C++ datafeed callback */
594 class SR_PRIV DatafeedCallbackData
595 {
596 public:
597         void run(const struct sr_dev_inst *sdi,
598                 const struct sr_datafeed_packet *pkt);
599 private:
600         DatafeedCallbackFunction _callback;
601         DatafeedCallbackData(Session *session,
602                 DatafeedCallbackFunction callback);
603         Session *_session;
604         friend class Session;
605 };
606
607 /** A virtual device associated with a stored session */
608 class SR_API SessionDevice :
609         public ParentOwned<SessionDevice, Session, struct sr_dev_inst>,
610         public Device
611 {
612 private:
613         explicit SessionDevice(struct sr_dev_inst *sdi);
614         ~SessionDevice();
615         shared_ptr<Device> get_shared_from_this();
616         /** Deleter needed to allow shared_ptr use with protected destructor. */
617         class Deleter
618         {
619         public:
620                 void operator()(SessionDevice *device) { delete device; }
621         };
622         friend class Deleter;
623         friend class Session;
624 };
625
626 /** A sigrok session */
627 class SR_API Session : public UserOwned<Session, struct sr_session>
628 {
629 public:
630         /** Add a device to this session.
631          * @param device Device to add. */
632         void add_device(shared_ptr<Device> device);
633         /** List devices attached to this session. */
634         vector<shared_ptr<Device> > devices();
635         /** Remove all devices from this session. */
636         void remove_devices();
637         /** Add a datafeed callback to this session.
638          * @param callback Callback of the form callback(Device, Packet). */
639         void add_datafeed_callback(DatafeedCallbackFunction callback);
640         /** Remove all datafeed callbacks from this session. */
641         void remove_datafeed_callbacks();
642         /** Start the session. */
643         void start();
644         /** Run the session event loop. */
645         void run();
646         /** Stop the session. */
647         void stop();
648         /** Return whether the session is running. */
649         bool is_running() const;
650         /** Set callback to be invoked on session stop. */
651         void set_stopped_callback(SessionStoppedCallback callback);
652         /** Get current trigger setting. */
653         shared_ptr<Trigger> trigger();
654         /** Get the context. */
655         shared_ptr<Context> context();
656         /** Set trigger setting.
657          * @param trigger Trigger object to use. */
658         void set_trigger(shared_ptr<Trigger> trigger);
659         /** Get filename this session was loaded from. */
660         string filename() const;
661 private:
662         explicit Session(shared_ptr<Context> context);
663         Session(shared_ptr<Context> context, string filename);
664         ~Session();
665         shared_ptr<Device> get_device(const struct sr_dev_inst *sdi);
666         const shared_ptr<Context> _context;
667         map<const struct sr_dev_inst *, SessionDevice *> _owned_devices;
668         map<const struct sr_dev_inst *, shared_ptr<Device> > _other_devices;
669         vector<DatafeedCallbackData *> _datafeed_callbacks;
670         SessionStoppedCallback _stopped_callback;
671         string _filename;
672         shared_ptr<Trigger> _trigger;
673         friend class Deleter;
674         friend class Context;
675         friend class DatafeedCallbackData;
676         friend class SessionDevice;
677 };
678
679 /** A packet on the session datafeed */
680 class SR_API Packet : public UserOwned<Packet, const struct sr_datafeed_packet>
681 {
682 public:
683         /** Type of this packet. */
684         const PacketType *type() const;
685         /** Payload of this packet. */
686         shared_ptr<PacketPayload> payload();
687 private:
688         Packet(shared_ptr<Device> device,
689                 const struct sr_datafeed_packet *structure);
690         ~Packet();
691         shared_ptr<Device> _device;
692         PacketPayload *_payload;
693         friend class Deleter;
694         friend class Session;
695         friend class Output;
696         friend class DatafeedCallbackData;
697         friend class Header;
698         friend class Meta;
699         friend class Logic;
700         friend class Analog;
701         friend class Context;
702 };
703
704 /** Abstract base class for datafeed packet payloads */
705 class SR_API PacketPayload
706 {
707 protected:
708         PacketPayload();
709         virtual ~PacketPayload() = 0;
710 private:
711         virtual shared_ptr<PacketPayload> get_shared_pointer(shared_ptr<Packet> parent) = 0;
712
713         /** Deleter needed to allow shared_ptr use with protected destructor. */
714         class Deleter
715         {
716         public:
717                 void operator()(PacketPayload *payload) { delete payload; }
718         };
719         friend class Deleter;
720         friend class Packet;
721         friend class Output;
722 };
723
724 /** Payload of a datafeed header packet */
725 class SR_API Header :
726         public ParentOwned<Header, Packet, const struct sr_datafeed_header>,
727         public PacketPayload
728 {
729 public:
730         /* Feed version number. */
731         int feed_version() const;
732         /* Start time of this session. */
733         Glib::TimeVal start_time() const;
734 private:
735         explicit Header(const struct sr_datafeed_header *structure);
736         ~Header();
737         shared_ptr<PacketPayload> get_shared_pointer(shared_ptr<Packet> parent);
738         friend class Packet;
739 };
740
741 /** Payload of a datafeed metadata packet */
742 class SR_API Meta :
743         public ParentOwned<Meta, Packet, const struct sr_datafeed_meta>,
744         public PacketPayload
745 {
746 public:
747         /* Mapping of (ConfigKey, value) pairs. */
748         map<const ConfigKey *, Glib::VariantBase> config() const;
749 private:
750         explicit Meta(const struct sr_datafeed_meta *structure);
751         ~Meta();
752         shared_ptr<PacketPayload> get_shared_pointer(shared_ptr<Packet> parent);
753         map<const ConfigKey *, Glib::VariantBase> _config;
754         friend class Packet;
755 };
756
757 /** Payload of a datafeed packet with logic data */
758 class SR_API Logic :
759         public ParentOwned<Logic, Packet, const struct sr_datafeed_logic>,
760         public PacketPayload
761 {
762 public:
763         /* Pointer to data. */
764         void *data_pointer();
765         /* Data length in bytes. */
766         size_t data_length() const;
767         /* Size of each sample in bytes. */
768         unsigned int unit_size() const;
769 private:
770         explicit Logic(const struct sr_datafeed_logic *structure);
771         ~Logic();
772         shared_ptr<PacketPayload> get_shared_pointer(shared_ptr<Packet> parent);
773         friend class Packet;
774 };
775
776 /** Payload of a datafeed packet with analog data */
777 class SR_API Analog :
778         public ParentOwned<Analog, Packet, const struct sr_datafeed_analog>,
779         public PacketPayload
780 {
781 public:
782         /** Pointer to data. */
783         void *data_pointer();
784         /** Number of samples in this packet. */
785         unsigned int num_samples() const;
786         /** Channels for which this packet contains data. */
787         vector<shared_ptr<Channel> > channels();
788         /** Measured quantity of the samples in this packet. */
789         const Quantity *mq() const;
790         /** Unit of the samples in this packet. */
791         const Unit *unit() const;
792         /** Measurement flags associated with the samples in this packet. */
793         vector<const QuantityFlag *> mq_flags() const;
794 private:
795         explicit Analog(const struct sr_datafeed_analog *structure);
796         ~Analog();
797         shared_ptr<PacketPayload> get_shared_pointer(shared_ptr<Packet> parent);
798         friend class Packet;
799 };
800
801 /** An input format supported by the library */
802 class SR_API InputFormat :
803         public ParentOwned<InputFormat, Context, const struct sr_input_module>
804 {
805 public:
806         /** Name of this input format. */
807         string name() const;
808         /** Description of this input format. */
809         string description() const;
810         /** A list of preferred file name extensions for this file format.
811          * @note This list is a recommendation only. */
812         vector<string> extensions() const;
813         /** Options supported by this input format. */
814         map<string, shared_ptr<Option> > options();
815         /** Create an input using this input format.
816          * @param options Mapping of (option name, value) pairs. */
817         shared_ptr<Input> create_input(const map<string, Glib::VariantBase> &options = {});
818 private:
819         explicit InputFormat(const struct sr_input_module *structure);
820         ~InputFormat();
821         friend class Context;
822         friend class InputDevice;
823 };
824
825 /** An input instance (an input format applied to a file or stream) */
826 class SR_API Input : public UserOwned<Input, const struct sr_input>
827 {
828 public:
829         /** Virtual device associated with this input. */
830         shared_ptr<InputDevice> device();
831         /** Send next stream data.
832          * @param data Next stream data.
833          * @param length Length of data. */
834         void send(void *data, size_t length);
835         /** Signal end of input data. */
836         void end();
837 private:
838         Input(shared_ptr<Context> context, const struct sr_input *structure);
839         ~Input();
840         shared_ptr<Context> _context;
841         InputDevice *_device;
842         friend class Deleter;
843         friend class Context;
844         friend class InputFormat;
845 };
846
847 /** A virtual device associated with an input */
848 class SR_API InputDevice :
849         public ParentOwned<InputDevice, Input, struct sr_dev_inst>,
850         public Device
851 {
852 private:
853         InputDevice(shared_ptr<Input> input, struct sr_dev_inst *sdi);
854         ~InputDevice();
855         shared_ptr<Device> get_shared_from_this();
856         shared_ptr<Input> _input;
857         friend class Input;
858 };
859
860 /** An option used by an output format */
861 class SR_API Option : public UserOwned<Option, const struct sr_option>
862 {
863 public:
864         /** Short name of this option suitable for command line usage. */
865         string id() const;
866         /** Short name of this option suitable for GUI usage. */
867         string name() const;
868         /** Description of this option in a sentence. */
869         string description() const;
870         /** Default value for this option. */
871         Glib::VariantBase default_value() const;
872         /** Possible values for this option, if a limited set. */
873         vector<Glib::VariantBase> values() const;
874 private:
875         Option(const struct sr_option *structure,
876                 shared_ptr<const struct sr_option *> structure_array);
877         ~Option();
878         shared_ptr<const struct sr_option *> _structure_array;
879         friend class Deleter;
880         friend class InputFormat;
881         friend class OutputFormat;
882 };
883
884 /** An output format supported by the library */
885 class SR_API OutputFormat :
886         public ParentOwned<OutputFormat, Context, const struct sr_output_module>
887 {
888 public:
889         /** Name of this output format. */
890         string name() const;
891         /** Description of this output format. */
892         string description() const;
893         /** A list of preferred file name extensions for this file format.
894          * @note This list is a recommendation only. */
895         vector<string> extensions() const;
896         /** Options supported by this output format. */
897         map<string, shared_ptr<Option> > options();
898         /** Create an output using this format.
899          * @param device Device to output for.
900          * @param options Mapping of (option name, value) pairs. */
901         shared_ptr<Output> create_output(
902                 shared_ptr<Device> device,
903                 const map<string, Glib::VariantBase> &options = {});
904         /** Create an output using this format.
905          * @param filename Name of destination file.
906          * @param device Device to output for.
907          * @param options Mapping of (option name, value) pairs. */
908         shared_ptr<Output> create_output(string filename,
909                 shared_ptr<Device> device,
910                 const map<string, Glib::VariantBase> &options = {});
911         /**
912          * Checks whether a given flag is set.
913          * @param flag Flag to check
914          * @return true if flag is set for this module
915          * @see sr_output_flags
916          */
917         bool test_flag(const OutputFlag *flag) const;
918 private:
919         explicit OutputFormat(const struct sr_output_module *structure);
920         ~OutputFormat();
921         friend class Context;
922         friend class Output;
923 };
924
925 /** An output instance (an output format applied to a device) */
926 class SR_API Output : public UserOwned<Output, const struct sr_output>
927 {
928 public:
929         /** Update output with data from the given packet.
930          * @param packet Packet to handle. */
931         string receive(shared_ptr<Packet> packet);
932 private:
933         Output(shared_ptr<OutputFormat> format, shared_ptr<Device> device);
934         Output(shared_ptr<OutputFormat> format,
935                 shared_ptr<Device> device, const map<string, Glib::VariantBase> &options);
936         Output(string filename, shared_ptr<OutputFormat> format,
937                 shared_ptr<Device> device, const map<string, Glib::VariantBase> &options);
938         ~Output();
939         const shared_ptr<OutputFormat> _format;
940         const shared_ptr<Device> _device;
941         const map<string, Glib::VariantBase> _options;
942         friend class Deleter;
943         friend class OutputFormat;
944 };
945
946 /** Base class for objects which wrap an enumeration value from libsigrok */
947 template <class Class, typename Enum> class SR_API EnumValue
948 {
949 public:
950         /** The integer constant associated with this value. */
951         int id() const
952         {
953                 return static_cast<int>(_id);
954         }
955         /** The name associated with this value. */
956         string name() const
957         {
958                 return _name;
959         }
960         /** Get value associated with a given integer constant. */
961         static const Class *get(int id)
962         {
963                 const auto pos = _values.find(static_cast<Enum>(id));
964                 if (pos == _values.end())
965                         throw Error(SR_ERR_ARG);
966                 return pos->second;
967         }
968         /** Get possible values. */
969         static std::vector<const Class *> values()
970         {
971                 std::vector<const Class *> result;
972                 for (auto entry : _values)
973                         result.push_back(entry.second);
974                 return result;
975         }
976 protected:
977         EnumValue(Enum id, const char name[]) : _id(id), _name(name)
978         {
979         }
980         ~EnumValue()
981         {
982         }
983 private:
984         static const std::map<const Enum, const Class * const> _values;
985         const Enum _id;
986         const string _name;
987 };
988
989 #include <libsigrokcxx/enums.hpp>
990
991 }
992
993 #endif