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