]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp
C++: Use smart pointers instead of manual delete
[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, unique_ptr<Driver> > _drivers;
304         map<string, unique_ptr<InputFormat> > _input_formats;
305         map<string, unique_ptr<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         friend class std::default_delete<Driver>;
374 };
375
376 /** A generic device, either hardware or virtual */
377 class SR_API Device : public Configurable
378 {
379 public:
380         /** Vendor name for this device. */
381         string vendor() const;
382         /** Model name for this device. */
383         string model() const;
384         /** Version string for this device. */
385         string version() const;
386         /** Serial number for this device. */
387         string serial_number() const;
388         /** Connection ID for this device. */
389         string connection_id() const;
390         /** List of the channels available on this device. */
391         vector<shared_ptr<Channel> > channels();
392         /** Channel groups available on this device, indexed by name. */
393         map<string, shared_ptr<ChannelGroup> > channel_groups();
394         /** Open device. */
395         void open();
396         /** Close device. */
397         void close();
398 protected:
399         explicit Device(struct sr_dev_inst *structure);
400         ~Device();
401         virtual shared_ptr<Device> get_shared_from_this() = 0;
402         shared_ptr<Channel> get_channel(struct sr_channel *ptr);
403
404         struct sr_dev_inst *_structure;
405         map<struct sr_channel *, unique_ptr<Channel> > _channels;
406 private:
407         map<string, unique_ptr<ChannelGroup> > _channel_groups;
408         /** Deleter needed to allow shared_ptr use with protected destructor. */
409         class Deleter
410         {
411         public:
412                 void operator()(Device *device) { delete device; }
413         };
414         friend class Deleter;
415         friend class Session;
416         friend class Channel;
417         friend class ChannelGroup;
418         friend class Output;
419         friend class Analog;
420 };
421
422 /** A real hardware device, connected via a driver */
423 class SR_API HardwareDevice :
424         public UserOwned<HardwareDevice>,
425         public Device
426 {
427 public:
428         /** Driver providing this device. */
429         shared_ptr<Driver> driver();
430 private:
431         HardwareDevice(shared_ptr<Driver> driver, struct sr_dev_inst *structure);
432         ~HardwareDevice();
433         shared_ptr<Device> get_shared_from_this();
434         shared_ptr<Driver> _driver;
435         /** Deleter needed to allow shared_ptr use with protected destructor. */
436         class Deleter
437         {
438         public:
439                 void operator()(HardwareDevice *device) { delete device; }
440         };
441         friend class Deleter;
442         friend class Driver;
443         friend class ChannelGroup;
444 };
445
446 /** A virtual device, created by the user */
447 class SR_API UserDevice :
448         public UserOwned<UserDevice>,
449         public Device
450 {
451 public:
452         /** Add a new channel to this device. */
453         shared_ptr<Channel> add_channel(unsigned int index, const ChannelType *type, string name);
454 private:
455         UserDevice(string vendor, string model, string version);
456         ~UserDevice();
457         shared_ptr<Device> get_shared_from_this();
458         /** Deleter needed to allow shared_ptr use with protected destructor. */
459         class Deleter
460         {
461         public:
462                 void operator()(UserDevice *device) { delete device; }
463         };
464         friend class Context;
465         friend class Deleter;
466 };
467
468 /** A channel on a device */
469 class SR_API Channel :
470         public ParentOwned<Channel, Device>
471 {
472 public:
473         /** Current name of this channel. */
474         string name() const;
475         /** Set the name of this channel. *
476          * @param name Name string to set. */
477         void set_name(string name);
478         /** Type of this channel. */
479         const ChannelType *type() const;
480         /** Enabled status of this channel. */
481         bool enabled() const;
482         /** Set the enabled status of this channel.
483          * @param value Boolean value to set. */
484         void set_enabled(bool value);
485         /** Get the index number of this channel. */
486         unsigned int index() const;
487 private:
488         explicit Channel(struct sr_channel *structure);
489         ~Channel();
490         struct sr_channel *_structure;
491         const ChannelType * const _type;
492         friend class Device;
493         friend class UserDevice;
494         friend class ChannelGroup;
495         friend class Session;
496         friend class TriggerStage;
497         friend class Context;
498         friend class std::default_delete<Channel>;
499 };
500
501 /** A group of channels on a device, which share some configuration */
502 class SR_API ChannelGroup :
503         public ParentOwned<ChannelGroup, Device>,
504         public Configurable
505 {
506 public:
507         /** Name of this channel group. */
508         string name() const;
509         /** List of the channels in this group. */
510         vector<shared_ptr<Channel> > channels();
511 private:
512         ChannelGroup(const Device *device, struct sr_channel_group *structure);
513         ~ChannelGroup();
514         vector<Channel *> _channels;
515         friend class Device;
516         friend class std::default_delete<ChannelGroup>;
517 };
518
519 /** A trigger configuration */
520 class SR_API Trigger : public UserOwned<Trigger>
521 {
522 public:
523         /** Name of this trigger configuration. */
524         string name() const;
525         /** List of the stages in this trigger. */
526         vector<shared_ptr<TriggerStage> > stages();
527         /** Add a new stage to this trigger. */
528         shared_ptr<TriggerStage> add_stage();
529 private:
530         Trigger(shared_ptr<Context> context, string name);
531         ~Trigger();
532         struct sr_trigger *_structure;
533         shared_ptr<Context> _context;
534         vector<unique_ptr<TriggerStage> > _stages;
535         friend class Deleter;
536         friend class Context;
537         friend class Session;
538 };
539
540 /** A stage in a trigger configuration */
541 class SR_API TriggerStage :
542         public ParentOwned<TriggerStage, Trigger>
543 {
544 public:
545         /** Index number of this stage. */
546         int number() const;
547         /** List of match conditions on this stage. */
548         vector<shared_ptr<TriggerMatch> > matches();
549         /** Add a new match condition to this stage.
550          * @param channel Channel to match on.
551          * @param type TriggerMatchType to apply. */
552         void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type);
553         /** Add a new match condition to this stage.
554          * @param channel Channel to match on.
555          * @param type TriggerMatchType to apply.
556          * @param value Threshold value. */
557         void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
558 private:
559         struct sr_trigger_stage *_structure;
560         vector<unique_ptr<TriggerMatch> > _matches;
561         explicit TriggerStage(struct sr_trigger_stage *structure);
562         ~TriggerStage();
563         friend class Trigger;
564         friend class std::default_delete<TriggerStage>;
565 };
566
567 /** A match condition in a trigger configuration  */
568 class SR_API TriggerMatch :
569         public ParentOwned<TriggerMatch, TriggerStage>
570 {
571 public:
572         /** Channel this condition matches on. */
573         shared_ptr<Channel> channel();
574         /** Type of match. */
575         const TriggerMatchType *type() const;
576         /** Threshold value. */
577         float value() const;
578 private:
579         TriggerMatch(struct sr_trigger_match *structure, shared_ptr<Channel> channel);
580         ~TriggerMatch();
581         struct sr_trigger_match *_structure;
582         shared_ptr<Channel> _channel;
583         friend class TriggerStage;
584         friend class std::default_delete<TriggerMatch>;
585 };
586
587 /** Type of session stopped callback */
588 typedef function<void()> SessionStoppedCallback;
589
590 /** Type of datafeed callback */
591 typedef function<void(shared_ptr<Device>, shared_ptr<Packet>)>
592         DatafeedCallbackFunction;
593
594 /* Data required for C callback function to call a C++ datafeed callback */
595 class SR_PRIV DatafeedCallbackData
596 {
597 public:
598         void run(const struct sr_dev_inst *sdi,
599                 const struct sr_datafeed_packet *pkt);
600 private:
601         DatafeedCallbackFunction _callback;
602         DatafeedCallbackData(Session *session,
603                 DatafeedCallbackFunction callback);
604         Session *_session;
605         friend class Session;
606 };
607
608 /** A virtual device associated with a stored session */
609 class SR_API SessionDevice :
610         public ParentOwned<SessionDevice, Session>,
611         public Device
612 {
613 private:
614         explicit SessionDevice(struct sr_dev_inst *sdi);
615         ~SessionDevice();
616         shared_ptr<Device> get_shared_from_this();
617         /** Deleter needed to allow shared_ptr use with protected destructor. */
618         class Deleter
619         {
620         public:
621                 void operator()(SessionDevice *device) { delete device; }
622         };
623         friend class Deleter;
624         friend class Session;
625         friend class std::default_delete<SessionDevice>;
626 };
627
628 /** A sigrok session */
629 class SR_API Session : public UserOwned<Session>
630 {
631 public:
632         /** Add a device to this session.
633          * @param device Device to add. */
634         void add_device(shared_ptr<Device> device);
635         /** List devices attached to this session. */
636         vector<shared_ptr<Device> > devices();
637         /** Remove all devices from this session. */
638         void remove_devices();
639         /** Add a datafeed callback to this session.
640          * @param callback Callback of the form callback(Device, Packet). */
641         void add_datafeed_callback(DatafeedCallbackFunction callback);
642         /** Remove all datafeed callbacks from this session. */
643         void remove_datafeed_callbacks();
644         /** Start the session. */
645         void start();
646         /** Run the session event loop. */
647         void run();
648         /** Stop the session. */
649         void stop();
650         /** Return whether the session is running. */
651         bool is_running() const;
652         /** Set callback to be invoked on session stop. */
653         void set_stopped_callback(SessionStoppedCallback callback);
654         /** Get current trigger setting. */
655         shared_ptr<Trigger> trigger();
656         /** Get the context. */
657         shared_ptr<Context> context();
658         /** Set trigger setting.
659          * @param trigger Trigger object to use. */
660         void set_trigger(shared_ptr<Trigger> trigger);
661         /** Get filename this session was loaded from. */
662         string filename() const;
663 private:
664         explicit Session(shared_ptr<Context> context);
665         Session(shared_ptr<Context> context, string filename);
666         ~Session();
667         shared_ptr<Device> get_device(const struct sr_dev_inst *sdi);
668         struct sr_session *_structure;
669         const shared_ptr<Context> _context;
670         map<const struct sr_dev_inst *, unique_ptr<SessionDevice> > _owned_devices;
671         map<const struct sr_dev_inst *, shared_ptr<Device> > _other_devices;
672         vector<unique_ptr<DatafeedCallbackData> > _datafeed_callbacks;
673         SessionStoppedCallback _stopped_callback;
674         string _filename;
675         shared_ptr<Trigger> _trigger;
676         friend class Deleter;
677         friend class Context;
678         friend class DatafeedCallbackData;
679         friend class SessionDevice;
680 };
681
682 /** A packet on the session datafeed */
683 class SR_API Packet : public UserOwned<Packet>
684 {
685 public:
686         /** Type of this packet. */
687         const PacketType *type() const;
688         /** Payload of this packet. */
689         shared_ptr<PacketPayload> payload();
690 private:
691         Packet(shared_ptr<Device> device,
692                 const struct sr_datafeed_packet *structure);
693         ~Packet();
694         const struct sr_datafeed_packet *_structure;
695         shared_ptr<Device> _device;
696         unique_ptr<PacketPayload> _payload;
697         friend class Deleter;
698         friend class Session;
699         friend class Output;
700         friend class DatafeedCallbackData;
701         friend class Header;
702         friend class Meta;
703         friend class Logic;
704         friend class Analog;
705         friend class Context;
706 };
707
708 /** Abstract base class for datafeed packet payloads */
709 class SR_API PacketPayload
710 {
711 protected:
712         PacketPayload();
713         virtual ~PacketPayload() = 0;
714 private:
715         virtual shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent) = 0;
716
717         /** Deleter needed to allow shared_ptr use with protected destructor. */
718         class Deleter
719         {
720         public:
721                 void operator()(PacketPayload *payload) { delete payload; }
722         };
723         friend class Deleter;
724         friend class Packet;
725         friend class Output;
726         friend class std::default_delete<PacketPayload>;
727 };
728
729 /** Payload of a datafeed header packet */
730 class SR_API Header :
731         public ParentOwned<Header, Packet>,
732         public PacketPayload
733 {
734 public:
735         /* Feed version number. */
736         int feed_version() const;
737         /* Start time of this session. */
738         Glib::TimeVal start_time() const;
739 private:
740         explicit Header(const struct sr_datafeed_header *structure);
741         ~Header();
742         shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
743
744         const struct sr_datafeed_header *_structure;
745
746         friend class Packet;
747 };
748
749 /** Payload of a datafeed metadata packet */
750 class SR_API Meta :
751         public ParentOwned<Meta, Packet>,
752         public PacketPayload
753 {
754 public:
755         /* Mapping of (ConfigKey, value) pairs. */
756         map<const ConfigKey *, Glib::VariantBase> config() const;
757 private:
758         explicit Meta(const struct sr_datafeed_meta *structure);
759         ~Meta();
760         shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
761
762         const struct sr_datafeed_meta *_structure;
763         map<const ConfigKey *, Glib::VariantBase> _config;
764
765         friend class Packet;
766 };
767
768 /** Payload of a datafeed packet with logic data */
769 class SR_API Logic :
770         public ParentOwned<Logic, Packet>,
771         public PacketPayload
772 {
773 public:
774         /* Pointer to data. */
775         void *data_pointer();
776         /* Data length in bytes. */
777         size_t data_length() const;
778         /* Size of each sample in bytes. */
779         unsigned int unit_size() const;
780 private:
781         explicit Logic(const struct sr_datafeed_logic *structure);
782         ~Logic();
783         shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
784
785         const struct sr_datafeed_logic *_structure;
786
787         friend class Packet;
788 };
789
790 /** Payload of a datafeed packet with analog data */
791 class SR_API Analog :
792         public ParentOwned<Analog, Packet>,
793         public PacketPayload
794 {
795 public:
796         /** Pointer to data. */
797         void *data_pointer();
798         /** Number of samples in this packet. */
799         unsigned int num_samples() const;
800         /** Channels for which this packet contains data. */
801         vector<shared_ptr<Channel> > channels();
802         /** Measured quantity of the samples in this packet. */
803         const Quantity *mq() const;
804         /** Unit of the samples in this packet. */
805         const Unit *unit() const;
806         /** Measurement flags associated with the samples in this packet. */
807         vector<const QuantityFlag *> mq_flags() const;
808 private:
809         explicit Analog(const struct sr_datafeed_analog *structure);
810         ~Analog();
811         shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
812
813         const struct sr_datafeed_analog *_structure;
814
815         friend class Packet;
816 };
817
818 /** An input format supported by the library */
819 class SR_API InputFormat :
820         public ParentOwned<InputFormat, Context>
821 {
822 public:
823         /** Name of this input format. */
824         string name() const;
825         /** Description of this input format. */
826         string description() const;
827         /** A list of preferred file name extensions for this file format.
828          * @note This list is a recommendation only. */
829         vector<string> extensions() const;
830         /** Options supported by this input format. */
831         map<string, shared_ptr<Option> > options();
832         /** Create an input using this input format.
833          * @param options Mapping of (option name, value) pairs. */
834         shared_ptr<Input> create_input(const map<string, Glib::VariantBase> &options = {});
835 private:
836         explicit InputFormat(const struct sr_input_module *structure);
837         ~InputFormat();
838
839         const struct sr_input_module *_structure;
840
841         friend class Context;
842         friend class InputDevice;
843         friend class std::default_delete<InputFormat>;
844 };
845
846 /** An input instance (an input format applied to a file or stream) */
847 class SR_API Input : public UserOwned<Input>
848 {
849 public:
850         /** Virtual device associated with this input. */
851         shared_ptr<InputDevice> device();
852         /** Send next stream data.
853          * @param data Next stream data.
854          * @param length Length of data. */
855         void send(void *data, size_t length);
856         /** Signal end of input data. */
857         void end();
858 private:
859         Input(shared_ptr<Context> context, const struct sr_input *structure);
860         ~Input();
861         const struct sr_input *_structure;
862         shared_ptr<Context> _context;
863         unique_ptr<InputDevice> _device;
864         friend class Deleter;
865         friend class Context;
866         friend class InputFormat;
867 };
868
869 /** A virtual device associated with an input */
870 class SR_API InputDevice :
871         public ParentOwned<InputDevice, Input>,
872         public Device
873 {
874 private:
875         InputDevice(shared_ptr<Input> input, struct sr_dev_inst *sdi);
876         ~InputDevice();
877         shared_ptr<Device> get_shared_from_this();
878         shared_ptr<Input> _input;
879         friend class Input;
880         friend class std::default_delete<InputDevice>;
881 };
882
883 /** An option used by an output format */
884 class SR_API Option : public UserOwned<Option>
885 {
886 public:
887         /** Short name of this option suitable for command line usage. */
888         string id() const;
889         /** Short name of this option suitable for GUI usage. */
890         string name() const;
891         /** Description of this option in a sentence. */
892         string description() const;
893         /** Default value for this option. */
894         Glib::VariantBase default_value() const;
895         /** Possible values for this option, if a limited set. */
896         vector<Glib::VariantBase> values() const;
897 private:
898         Option(const struct sr_option *structure,
899                 shared_ptr<const struct sr_option *> structure_array);
900         ~Option();
901         const struct sr_option *_structure;
902         shared_ptr<const struct sr_option *> _structure_array;
903         friend class Deleter;
904         friend class InputFormat;
905         friend class OutputFormat;
906 };
907
908 /** An output format supported by the library */
909 class SR_API OutputFormat :
910         public ParentOwned<OutputFormat, Context>
911 {
912 public:
913         /** Name of this output format. */
914         string name() const;
915         /** Description of this output format. */
916         string description() const;
917         /** A list of preferred file name extensions for this file format.
918          * @note This list is a recommendation only. */
919         vector<string> extensions() const;
920         /** Options supported by this output format. */
921         map<string, shared_ptr<Option> > options();
922         /** Create an output using this format.
923          * @param device Device to output for.
924          * @param options Mapping of (option name, value) pairs. */
925         shared_ptr<Output> create_output(
926                 shared_ptr<Device> device,
927                 const map<string, Glib::VariantBase> &options = {});
928         /** Create an output using this format.
929          * @param filename Name of destination file.
930          * @param device Device to output for.
931          * @param options Mapping of (option name, value) pairs. */
932         shared_ptr<Output> create_output(string filename,
933                 shared_ptr<Device> device,
934                 const map<string, Glib::VariantBase> &options = {});
935         /**
936          * Checks whether a given flag is set.
937          * @param flag Flag to check
938          * @return true if flag is set for this module
939          * @see sr_output_flags
940          */
941         bool test_flag(const OutputFlag *flag) const;
942 private:
943         explicit OutputFormat(const struct sr_output_module *structure);
944         ~OutputFormat();
945
946         const struct sr_output_module *_structure;
947
948         friend class Context;
949         friend class Output;
950         friend class std::default_delete<OutputFormat>;
951 };
952
953 /** An output instance (an output format applied to a device) */
954 class SR_API Output : public UserOwned<Output>
955 {
956 public:
957         /** Update output with data from the given packet.
958          * @param packet Packet to handle. */
959         string receive(shared_ptr<Packet> packet);
960 private:
961         Output(shared_ptr<OutputFormat> format, shared_ptr<Device> device);
962         Output(shared_ptr<OutputFormat> format,
963                 shared_ptr<Device> device, const map<string, Glib::VariantBase> &options);
964         Output(string filename, shared_ptr<OutputFormat> format,
965                 shared_ptr<Device> device, const map<string, Glib::VariantBase> &options);
966         ~Output();
967
968         const struct sr_output *_structure;
969         const shared_ptr<OutputFormat> _format;
970         const shared_ptr<Device> _device;
971         const map<string, Glib::VariantBase> _options;
972
973         friend class Deleter;
974         friend class OutputFormat;
975 };
976
977 /** Base class for objects which wrap an enumeration value from libsigrok */
978 template <class Class, typename Enum> class SR_API EnumValue
979 {
980 public:
981         /** The integer constant associated with this value. */
982         int id() const
983         {
984                 return static_cast<int>(_id);
985         }
986         /** The name associated with this value. */
987         string name() const
988         {
989                 return _name;
990         }
991         /** Get value associated with a given integer constant. */
992         static const Class *get(int id)
993         {
994                 const auto pos = _values.find(static_cast<Enum>(id));
995                 if (pos == _values.end())
996                         throw Error(SR_ERR_ARG);
997                 return pos->second;
998         }
999         /** Get possible values. */
1000         static std::vector<const Class *> values()
1001         {
1002                 std::vector<const Class *> result;
1003                 for (auto entry : _values)
1004                         result.push_back(entry.second);
1005                 return result;
1006         }
1007 protected:
1008         EnumValue(Enum id, const char name[]) : _id(id), _name(name)
1009         {
1010         }
1011         ~EnumValue()
1012         {
1013         }
1014 private:
1015         static const std::map<const Enum, const Class * const> _values;
1016         const Enum _id;
1017         const string _name;
1018 };
1019
1020 #include <libsigrokcxx/enums.hpp>
1021
1022 }
1023
1024 #endif