]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/classes.cpp
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / bindings / cxx / classes.cpp
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 #include "libsigrok/libsigrok.hpp"
21
22 #include <sstream>
23
24 namespace sigrok
25 {
26
27 /** Helper function to translate C errors to C++ exceptions. */
28 static void check(int result)
29 {
30         if (result != SR_OK)
31                 throw Error(result);
32 }
33
34 /** Helper function to obtain valid strings from possibly null input. */
35 static const char *valid_string(const char *input)
36 {
37         if (input != NULL)
38                 return input;
39         else
40                 return "";
41 }
42
43 /** Helper function to convert between map<string, string> and GHashTable */
44 static GHashTable *map_to_hash_string(map<string, string> input)
45 {
46         auto output = g_hash_table_new_full(
47                 g_str_hash, g_str_equal, g_free, g_free);
48         for (auto entry : input)
49                 g_hash_table_insert(output,
50                         g_strdup(entry.first.c_str()),
51                         g_strdup(entry.second.c_str()));
52     return output;
53 }
54
55 /** Helper function to convert between map<string, VariantBase> and GHashTable */
56 static GHashTable *map_to_hash_variant(map<string, Glib::VariantBase> input)
57 {
58         auto output = g_hash_table_new_full(
59                 g_variant_hash, g_variant_equal, g_free,
60                 (void (*)(void *))g_variant_unref);
61         for (auto entry : input)
62                 g_hash_table_insert(output,
63                         g_strdup(entry.first.c_str()),
64                         entry.second.gobj_copy());
65     return output;
66 }
67
68 Error::Error(int result) : result(result)
69 {
70 }
71
72 const char *Error::what() const throw()
73 {
74         return sr_strerror(result);
75 }
76
77 Error::~Error() throw()
78 {
79 }
80
81 shared_ptr<Context> Context::create()
82 {
83         return shared_ptr<Context>(new Context(), Context::Deleter());
84 }
85
86 Context::Context() :
87         session(NULL)
88 {
89         check(sr_init(&structure));
90         struct sr_dev_driver **driver_list = sr_driver_list();
91         if (driver_list)
92                 for (int i = 0; driver_list[i]; i++)
93                         drivers[driver_list[i]->name] =
94                                 new Driver(driver_list[i]);
95         struct sr_input_format **input_list = sr_input_list();
96         if (input_list)
97                 for (int i = 0; input_list[i]; i++)
98                         input_formats[input_list[i]->id] =
99                                 new InputFormat(input_list[i]);
100         const struct sr_output_module **output_list = sr_output_list();
101         if (output_list)
102                 for (int i = 0; output_list[i]; i++)
103                         output_formats[sr_output_id_get(output_list[i])] =
104                                 new OutputFormat(output_list[i]);
105 }
106
107 string Context::get_package_version()
108 {
109         return sr_package_version_string_get();
110 }
111
112 string Context::get_lib_version()
113 {
114         return sr_lib_version_string_get();
115 }
116
117 map<string, shared_ptr<Driver>> Context::get_drivers()
118 {
119         map<string, shared_ptr<Driver>> result;
120         for (auto entry: drivers)
121         {
122                 auto name = entry.first;
123                 auto driver = entry.second;
124                 result[name] = static_pointer_cast<Driver>(
125                         driver->get_shared_pointer(this));
126         }
127         return result;
128 }
129
130 map<string, shared_ptr<InputFormat>> Context::get_input_formats()
131 {
132         map<string, shared_ptr<InputFormat>> result;
133         for (auto entry: input_formats)
134         {
135                 auto name = entry.first;
136                 auto input_format = entry.second;
137                 result[name] = static_pointer_cast<InputFormat>(
138                         input_format->get_shared_pointer(this));
139         }
140         return result;
141 }
142
143 map<string, shared_ptr<OutputFormat>> Context::get_output_formats()
144 {
145         map<string, shared_ptr<OutputFormat>> result;
146         for (auto entry: output_formats)
147         {
148                 auto name = entry.first;
149                 auto output_format = entry.second;
150                 result[name] = static_pointer_cast<OutputFormat>(
151                         output_format->get_shared_pointer(this));
152         }
153         return result;
154 }
155
156 Context::~Context()
157 {
158         for (auto entry : drivers)
159                 delete entry.second;
160         for (auto entry : input_formats)
161                 delete entry.second;
162         for (auto entry : output_formats)
163                 delete entry.second;
164         check(sr_exit(structure));
165 }
166
167 const LogLevel *Context::get_log_level()
168 {
169         return LogLevel::get(sr_log_loglevel_get());
170 }
171
172 void Context::set_log_level(const LogLevel *level)
173 {
174         check(sr_log_loglevel_set(level->get_id()));
175 }
176
177 string Context::get_log_domain()
178 {
179         return valid_string(sr_log_logdomain_get());
180 }
181
182 void Context::set_log_domain(string value)
183 {
184         check(sr_log_logdomain_set(value.c_str()));
185 }
186
187 static int call_log_callback(void *cb_data, int loglevel, const char *format, va_list args)
188 {
189         va_list args_copy;
190         va_copy(args_copy, args);
191         int length = vsnprintf(NULL, 0, format, args_copy);
192         va_end(args_copy);
193         char *buf = (char *) g_malloc(length + 1);
194         vsprintf(buf, format, args);
195         string message(buf, length);
196         g_free(buf);
197
198         LogCallbackFunction callback = *((LogCallbackFunction *) cb_data);
199
200         try
201         {
202                 callback(LogLevel::get(loglevel), message);
203         }
204         catch (Error e)
205         {
206                 return e.result;
207         }
208
209         return SR_OK;
210 }
211
212 void Context::set_log_callback(LogCallbackFunction callback)
213 {
214         log_callback = callback;
215         check(sr_log_callback_set(call_log_callback, &log_callback));
216
217
218 void Context::set_log_callback_default()
219 {
220         check(sr_log_callback_set_default());
221         log_callback = nullptr;
222
223
224 shared_ptr<Session> Context::create_session()
225 {
226         return shared_ptr<Session>(
227                 new Session(shared_from_this()), Session::Deleter());
228 }
229
230 shared_ptr<Session> Context::load_session(string filename)
231 {
232         return shared_ptr<Session>(
233                 new Session(shared_from_this(), filename), Session::Deleter());
234 }
235
236 shared_ptr<Trigger> Context::create_trigger(string name)
237 {
238         return shared_ptr<Trigger>(
239                 new Trigger(shared_from_this(), name), Trigger::Deleter());
240 }
241
242 Driver::Driver(struct sr_dev_driver *structure) :
243         StructureWrapper<Context, struct sr_dev_driver>(structure),
244         initialized(false)
245 {
246 }
247
248 Driver::~Driver()
249 {
250         for (auto device : devices)
251                 delete device;
252 }
253
254 string Driver::get_name()
255 {
256         return valid_string(structure->name);
257 }
258
259 string Driver::get_long_name()
260 {
261         return valid_string(structure->longname);
262 }
263
264 vector<shared_ptr<HardwareDevice>> Driver::scan(
265         map<const ConfigKey *, Glib::VariantBase> options)
266 {
267         /* Initialise the driver if not yet done. */
268         if (!initialized)
269         {
270                 check(sr_driver_init(parent->structure, structure));
271                 initialized = true;
272         }
273
274         /* Clear all existing instances. */
275         for (auto device : devices)
276                 delete device;
277         devices.clear();
278
279         /* Translate scan options to GSList of struct sr_config pointers. */
280         GSList *option_list = NULL;
281         for (auto entry : options)
282         {
283                 auto key = entry.first;
284                 auto value = entry.second;
285                 auto config = g_new(struct sr_config, 1);
286                 config->key = key->get_id();
287                 config->data = value.gobj();
288                 option_list = g_slist_append(option_list, config);
289         }
290
291         /* Run scan. */
292         GSList *device_list = sr_driver_scan(structure, option_list);
293
294         /* Free option list. */
295         g_slist_free_full(option_list, g_free);
296
297         /* Create device objects. */
298         for (GSList *device = device_list; device; device = device->next)
299         {
300                 auto sdi = (struct sr_dev_inst *) device->data;
301                 devices.push_back(new HardwareDevice(this, sdi));
302         }
303
304         /* Free GSList returned from scan. */
305         g_slist_free(device_list);
306
307         /* Create list of shared pointers to device instances for return. */
308         vector<shared_ptr<HardwareDevice>> result;
309         for (auto device : devices)
310                 result.push_back(static_pointer_cast<HardwareDevice>(
311                         device->get_shared_pointer(parent)));
312         return result;
313 }
314
315 Configurable::Configurable(
316                 struct sr_dev_driver *driver,
317                 struct sr_dev_inst *sdi,
318                 struct sr_channel_group *cg) :
319         config_driver(driver),
320         config_sdi(sdi),
321         config_channel_group(cg)
322 {
323 }
324
325 Configurable::~Configurable()
326 {
327 }
328
329 Glib::VariantBase Configurable::config_get(const ConfigKey *key)
330 {
331         GVariant *data;
332         check(sr_config_get(
333                 config_driver, config_sdi, config_channel_group,
334                 key->get_id(), &data));
335         return Glib::VariantBase(data);
336 }
337
338 void Configurable::config_set(const ConfigKey *key, Glib::VariantBase value)
339 {
340         check(sr_config_set(
341                 config_sdi, config_channel_group,
342                 key->get_id(), value.gobj()));
343 }
344
345 Glib::VariantContainerBase Configurable::config_list(const ConfigKey *key)
346 {
347         GVariant *data;
348         check(sr_config_list(
349                 config_driver, config_sdi, config_channel_group,
350                 key->get_id(), &data));
351         return Glib::VariantContainerBase(data);
352 }
353
354 Device::Device(struct sr_dev_inst *structure) :
355         Configurable(structure->driver, structure, NULL),
356         StructureWrapper<Context, struct sr_dev_inst>(structure)
357 {
358         for (GSList *entry = structure->channels; entry; entry = entry->next)
359         {
360                 auto channel = (struct sr_channel *) entry->data;
361                 channels[channel] = new Channel(channel);
362         }
363
364         for (GSList *entry = structure->channel_groups; entry; entry = entry->next)
365         {
366                 auto group = (struct sr_channel_group *) entry->data;
367                 channel_groups[group->name] = new ChannelGroup(this, group);
368         }
369 }
370
371 Device::~Device()
372 {
373         for (auto entry : channels)
374                 delete entry.second;
375         for (auto entry : channel_groups)
376                 delete entry.second;
377 }
378
379 string Device::get_description()
380 {
381         ostringstream s;
382
383         vector<string> parts =
384                 {get_vendor(), get_model(), get_version()};
385
386         for (string part : parts)
387                 if (part.length() > 0)
388                         s << part;
389
390         return s.str();
391 }
392
393 string Device::get_vendor()
394 {
395         return valid_string(structure->vendor);
396 }
397
398 string Device::get_model()
399 {
400         return valid_string(structure->model);
401 }
402
403 string Device::get_version()
404 {
405         return valid_string(structure->version);
406 }
407
408 vector<shared_ptr<Channel>> Device::get_channels()
409 {
410         vector<shared_ptr<Channel>> result;
411         for (auto entry : channels)
412                 result.push_back(static_pointer_cast<Channel>(
413                         entry.second->get_shared_pointer(this)));
414         return result;
415 }
416
417 shared_ptr<Channel> Device::get_channel(struct sr_channel *ptr)
418 {
419         return static_pointer_cast<Channel>(
420                 channels[ptr]->get_shared_pointer(this));
421 }
422
423 map<string, shared_ptr<ChannelGroup>>
424 Device::get_channel_groups()
425 {
426         map<string, shared_ptr<ChannelGroup>> result;
427         for (auto entry: channel_groups)
428         {
429                 auto name = entry.first;
430                 auto channel_group = entry.second;
431                 result[name] = static_pointer_cast<ChannelGroup>(
432                         channel_group->get_shared_pointer(this));
433         }
434         return result;
435 }
436
437 void Device::open()
438 {
439         check(sr_dev_open(structure));
440 }
441
442 void Device::close()
443 {
444         check(sr_dev_close(structure));
445 }
446
447 HardwareDevice::HardwareDevice(Driver *driver, struct sr_dev_inst *structure) :
448         Device(structure),
449         driver(driver)
450 {
451 }
452
453 HardwareDevice::~HardwareDevice()
454 {
455 }
456
457 shared_ptr<Driver> HardwareDevice::get_driver()
458 {
459         return static_pointer_cast<Driver>(driver->get_shared_pointer(parent));
460 }
461
462 Channel::Channel(struct sr_channel *structure) :
463         StructureWrapper<Device, struct sr_channel>(structure),
464         type(ChannelType::get(structure->type))
465 {
466 }
467
468 Channel::~Channel()
469 {
470 }
471
472 string Channel::get_name()
473 {
474         return valid_string(structure->name);
475 }
476
477 void Channel::set_name(string name)
478 {
479         check(sr_dev_channel_name_set(parent->structure, structure->index, name.c_str()));
480 }
481
482 const ChannelType *Channel::get_type()
483 {
484         return ChannelType::get(structure->type);
485 }
486
487 bool Channel::get_enabled()
488 {
489         return structure->enabled;
490 }
491
492 void Channel::set_enabled(bool value)
493 {
494         check(sr_dev_channel_enable(parent->structure, structure->index, value));
495 }
496
497 unsigned int Channel::get_index()
498 {
499         return structure->index;
500 }
501
502 ChannelGroup::ChannelGroup(Device *device,
503                 struct sr_channel_group *structure) :
504         StructureWrapper<Device, struct sr_channel_group>(structure),
505         Configurable(device->structure->driver, device->structure, structure)
506 {
507         for (GSList *entry = structure->channels; entry; entry = entry->next)
508                 channels.push_back(device->channels[(struct sr_channel *)entry->data]);
509 }
510
511 ChannelGroup::~ChannelGroup()
512 {
513 }
514
515 string ChannelGroup::get_name()
516 {
517         return valid_string(structure->name);
518 }
519
520 vector<shared_ptr<Channel>> ChannelGroup::get_channels()
521 {
522         vector<shared_ptr<Channel>> result;
523         for (auto channel : channels)
524                 result.push_back(static_pointer_cast<Channel>(
525                         channel->get_shared_pointer(parent)));
526         return result;
527 }
528
529 Trigger::Trigger(shared_ptr<Context> context, string name) : 
530         structure(sr_trigger_new(name.c_str())), context(context)
531 {
532         for (auto stage = structure->stages; stage; stage = stage->next)
533                 stages.push_back(new TriggerStage((struct sr_trigger_stage *) stage->data));
534 }
535
536 Trigger::~Trigger()
537 {
538         for (auto stage: stages)
539                 delete stage;
540
541         sr_trigger_free(structure);
542 }
543
544 string Trigger::get_name()
545 {
546         return structure->name;
547 }
548
549 vector<shared_ptr<TriggerStage>> Trigger::get_stages()
550 {
551         vector<shared_ptr<TriggerStage>> result;
552         for (auto stage : stages)
553                 result.push_back(static_pointer_cast<TriggerStage>(
554                         stage->get_shared_pointer(this)));
555         return result;
556 }
557
558 shared_ptr<TriggerStage> Trigger::add_stage()
559 {
560         auto stage = new TriggerStage(sr_trigger_stage_add(structure));
561         stages.push_back(stage);
562         return static_pointer_cast<TriggerStage>(
563                 stage->get_shared_pointer(this));
564 }
565
566 TriggerStage::TriggerStage(struct sr_trigger_stage *structure) : 
567         StructureWrapper<Trigger, struct sr_trigger_stage>(structure)
568 {
569 }
570
571 TriggerStage::~TriggerStage()
572 {
573         for (auto match : matches)
574                 delete match;
575 }
576         
577 int TriggerStage::get_number()
578 {
579         return structure->stage;
580 }
581
582 vector<shared_ptr<TriggerMatch>> TriggerStage::get_matches()
583 {
584         vector<shared_ptr<TriggerMatch>> result;
585         for (auto match : matches)
586                 result.push_back(static_pointer_cast<TriggerMatch>(
587                         match->get_shared_pointer(this)));
588         return result;
589 }
590
591 void TriggerStage::add_match(shared_ptr<Channel> channel, const TriggerMatchType *type, float value)
592 {
593         check(sr_trigger_match_add(structure, channel->structure, type->get_id(), value));
594         matches.push_back(new TriggerMatch(
595                 (struct sr_trigger_match *) g_slist_last(structure->matches)->data, channel));
596 }
597
598 void TriggerStage::add_match(shared_ptr<Channel> channel, const TriggerMatchType *type)
599 {
600         add_match(channel, type, NAN);
601 }
602
603 TriggerMatch::TriggerMatch(struct sr_trigger_match *structure, shared_ptr<Channel> channel) :
604         StructureWrapper<TriggerStage, struct sr_trigger_match>(structure), channel(channel)
605 {
606 }
607
608 TriggerMatch::~TriggerMatch()
609 {
610 }
611
612 shared_ptr<Channel> TriggerMatch::get_channel()
613 {
614         return channel;
615 }
616
617 const TriggerMatchType *TriggerMatch::get_type()
618 {
619         return TriggerMatchType::get(structure->match);
620 }
621
622 float TriggerMatch::get_value()
623 {
624         return structure->value;
625 }
626
627 DatafeedCallbackData::DatafeedCallbackData(Session *session,
628                 DatafeedCallbackFunction callback) :
629         callback(callback), session(session)
630 {
631 }
632
633 void DatafeedCallbackData::run(const struct sr_dev_inst *sdi,
634         const struct sr_datafeed_packet *pkt)
635 {
636         auto device = session->devices[sdi];
637         auto packet = shared_ptr<Packet>(new Packet(device, pkt), Packet::Deleter());
638         callback(device, packet);
639 }
640
641 SourceCallbackData::SourceCallbackData(shared_ptr<EventSource> source) :
642         source(source)
643 {
644 }
645
646 bool SourceCallbackData::run(int revents)
647 {
648         return source->callback((Glib::IOCondition) revents);
649 }
650
651 shared_ptr<EventSource> EventSource::create(int fd, Glib::IOCondition events,
652         int timeout, SourceCallbackFunction callback)
653 {
654         auto result = new EventSource(timeout, callback);
655         result->type = EventSource::SOURCE_FD;
656         result->fd = fd;
657         result->events = events;
658         return shared_ptr<EventSource>(result, EventSource::Deleter());
659 }
660
661 shared_ptr<EventSource> EventSource::create(Glib::PollFD pollfd, int timeout,
662         SourceCallbackFunction callback)
663 {
664         auto result = new EventSource(timeout, callback);
665         result->type = EventSource::SOURCE_POLLFD;
666         result->pollfd = pollfd;
667         return shared_ptr<EventSource>(result, EventSource::Deleter());
668 }
669
670 shared_ptr<EventSource> EventSource::create(Glib::RefPtr<Glib::IOChannel> channel,
671         Glib::IOCondition events, int timeout, SourceCallbackFunction callback)
672 {
673         auto result = new EventSource(timeout, callback);
674         result->type = EventSource::SOURCE_IOCHANNEL;
675         result->channel = channel;
676         result->events = events;
677         return shared_ptr<EventSource>(result, EventSource::Deleter());
678 }
679
680 EventSource::EventSource(int timeout, SourceCallbackFunction callback) :
681         timeout(timeout), callback(callback)
682 {
683 }
684
685 EventSource::~EventSource()
686 {
687 }
688
689 Session::Session(shared_ptr<Context> context) :
690         context(context), saving(false)
691 {
692         check(sr_session_new(&structure));
693         context->session = this;
694 }
695
696 Session::Session(shared_ptr<Context> context, string filename) :
697         context(context), saving(false)
698 {
699         check(sr_session_load(filename.c_str(), &structure));
700         context->session = this;
701 }
702
703 Session::~Session()
704 {
705         check(sr_session_destroy(structure));
706
707         for (auto callback : datafeed_callbacks)
708                 delete callback;
709
710         for (auto entry : source_callbacks)
711                 delete entry.second;
712 }
713
714 void Session::add_device(shared_ptr<Device> device)
715 {
716         check(sr_session_dev_add(structure, device->structure));
717         devices[device->structure] = device;
718 }
719
720 vector<shared_ptr<Device>> Session::get_devices()
721 {
722         GSList *dev_list;
723         check(sr_session_dev_list(structure, &dev_list));
724         vector<shared_ptr<Device>> result;
725         for (GSList *dev = dev_list; dev; dev = dev->next)
726         {
727                 auto sdi = (struct sr_dev_inst *) dev->data;
728                 if (devices.count(sdi) == 0)
729                         devices[sdi] = shared_ptr<Device>(
730                                 new Device(sdi), Device::Deleter());
731                 result.push_back(devices[sdi]);
732         }
733         return result;
734 }
735
736 void Session::remove_devices()
737 {
738         devices.clear();
739         check(sr_session_dev_remove_all(structure));
740 }
741
742 void Session::start()
743 {
744         check(sr_session_start(structure));
745 }
746
747 void Session::run()
748 {
749         check(sr_session_run(structure));
750 }
751
752 void Session::stop()
753 {
754         check(sr_session_stop(structure));
755 }
756
757 void Session::begin_save(string filename)
758 {
759         saving = true;
760         save_initialized = false;
761         save_filename = filename;
762         save_samplerate = 0;
763 }
764
765 void Session::append(shared_ptr<Packet> packet)
766 {
767         if (!saving)
768                 throw Error(SR_ERR);
769
770         switch (packet->structure->type)
771         {
772                 case SR_DF_META:
773                 {
774                         auto meta = (const struct sr_datafeed_meta *)
775                                 packet->structure->payload;
776
777                         for (auto l = meta->config; l; l = l->next)
778                         {
779                                 auto config = (struct sr_config *) l->data;
780                                 if (config->key == SR_CONF_SAMPLERATE)
781                                         save_samplerate = g_variant_get_uint64(config->data);
782                         }
783
784                         break;
785                 }
786                 case SR_DF_LOGIC:
787                 {
788                         if (save_samplerate == 0)
789                         {
790                                 GVariant *samplerate;
791
792                                 check(sr_config_get(packet->device->structure->driver,
793                                         packet->device->structure, NULL, SR_CONF_SAMPLERATE,
794                                         &samplerate));
795
796                                 save_samplerate = g_variant_get_uint64(samplerate);
797
798                                 g_variant_unref(samplerate);
799                         }
800
801                         if (!save_initialized)
802                         {
803                                 vector<shared_ptr<Channel>> save_channels;
804
805                                 for (auto channel : packet->device->get_channels())
806                                         if (channel->structure->enabled &&
807                                                         channel->structure->type == SR_CHANNEL_LOGIC)
808                                                 save_channels.push_back(channel);
809
810                                 auto channels = g_new(char *, save_channels.size());
811
812                                 int i = 0;
813                                 for (auto channel : save_channels)
814                                                 channels[i++] = channel->structure->name;
815                                 channels[i] = NULL;
816
817                                 int ret = sr_session_save_init(structure, save_filename.c_str(),
818                                                 save_samplerate, channels);
819
820                                 g_free(channels);
821
822                                 if (ret != SR_OK)
823                                         throw Error(ret);
824
825                                 save_initialized = true;
826                         }
827
828                         auto logic = (const struct sr_datafeed_logic *)
829                                 packet->structure->payload;
830
831                         check(sr_session_append(structure, save_filename.c_str(),
832                                 (uint8_t *) logic->data, logic->unitsize,
833                                 logic->length / logic->unitsize));
834                 }
835         }
836 }
837
838 void Session::append(void *data, size_t length, unsigned int unit_size)
839 {
840         check(sr_session_append(structure, save_filename.c_str(),
841                 (uint8_t *) data, unit_size, length));
842 }
843
844 static void datafeed_callback(const struct sr_dev_inst *sdi,
845         const struct sr_datafeed_packet *pkt, void *cb_data)
846 {
847         auto callback = static_cast<DatafeedCallbackData *>(cb_data);
848         callback->run(sdi, pkt);
849 }
850         
851 void Session::add_datafeed_callback(DatafeedCallbackFunction callback)
852 {
853         auto cb_data = new DatafeedCallbackData(this, callback);
854         check(sr_session_datafeed_callback_add(structure, datafeed_callback, cb_data));
855         datafeed_callbacks.push_back(cb_data);
856 }
857
858 void Session::remove_datafeed_callbacks(void)
859 {
860         check(sr_session_datafeed_callback_remove_all(structure));
861         for (auto callback : datafeed_callbacks)
862                 delete callback;
863         datafeed_callbacks.clear();
864 }
865
866 static int source_callback(int fd, int revents, void *cb_data)
867 {
868         (void) fd;
869         auto callback = (SourceCallbackData *) cb_data;
870         return callback->run(revents);
871 }
872
873 void Session::add_source(shared_ptr<EventSource> source)
874 {
875         if (source_callbacks.count(source) == 1)
876                 throw Error(SR_ERR_ARG);
877
878         auto cb_data = new SourceCallbackData(source);
879
880         switch (source->type)
881         {
882                 case EventSource::SOURCE_FD:
883                         check(sr_session_source_add(structure, source->fd, source->events,
884                                 source->timeout, source_callback, cb_data));
885                         break;
886                 case EventSource::SOURCE_POLLFD:
887                         check(sr_session_source_add_pollfd(structure,
888                                 source->pollfd.gobj(), source->timeout, source_callback,
889                                 cb_data));
890                         break;
891                 case EventSource::SOURCE_IOCHANNEL:
892                         check(sr_session_source_add_channel(structure,
893                                 source->channel->gobj(), source->events, source->timeout,
894                                 source_callback, cb_data));
895                         break;
896         }
897
898         source_callbacks[source] = cb_data;
899 }
900
901 void Session::remove_source(shared_ptr<EventSource> source)
902 {
903         if (source_callbacks.count(source) == 0)
904                 throw Error(SR_ERR_ARG);
905
906         switch (source->type)
907         {
908                 case EventSource::SOURCE_FD:
909                         check(sr_session_source_remove(structure, source->fd));
910                         break;
911                 case EventSource::SOURCE_POLLFD:
912                         check(sr_session_source_remove_pollfd(structure,
913                                 source->pollfd.gobj()));
914                         break;
915                 case EventSource::SOURCE_IOCHANNEL:
916                         check(sr_session_source_remove_channel(structure,
917                                 source->channel->gobj()));
918                         break;
919         }
920
921         delete source_callbacks[source];
922
923         source_callbacks.erase(source);
924 }
925
926 shared_ptr<Trigger> Session::get_trigger()
927 {
928         return trigger;
929 }
930
931 void Session::set_trigger(shared_ptr<Trigger> trigger)
932 {
933         check(sr_session_trigger_set(structure, trigger->structure));
934         this->trigger = trigger;
935 }
936
937 Packet::Packet(shared_ptr<Device> device,
938         const struct sr_datafeed_packet *structure) :
939         structure(structure),
940         device(device)
941 {
942         switch (structure->type)
943         {
944                 case SR_DF_HEADER:
945                         payload = new Header(
946                                 static_cast<const struct sr_datafeed_header *>(
947                                         structure->payload));
948                         break;
949                 case SR_DF_META:
950                         payload = new Meta(
951                                 static_cast<const struct sr_datafeed_meta *>(
952                                         structure->payload));
953                         break;
954                 case SR_DF_LOGIC:
955                         payload = new Logic(
956                                 static_cast<const struct sr_datafeed_logic *>(
957                                         structure->payload));
958                         break;
959                 case SR_DF_ANALOG:
960                         payload = new Analog(
961                                 static_cast<const struct sr_datafeed_analog *>(
962                                         structure->payload));
963                         break;
964         }
965 }
966
967 Packet::~Packet()
968 {
969         if (payload)
970                 delete payload;
971 }
972
973 const PacketType *Packet::get_type()
974 {
975         return PacketType::get(structure->type);
976 }
977
978 shared_ptr<PacketPayload> Packet::get_payload()
979 {
980         return payload->get_shared_pointer(this);
981 }
982
983 PacketPayload::PacketPayload()
984 {
985 }
986
987 PacketPayload::~PacketPayload()
988 {
989 }
990
991 Header::Header(const struct sr_datafeed_header *structure) :
992         PacketPayload(),
993         StructureWrapper<Packet, const struct sr_datafeed_header>(structure)
994 {
995 }
996
997 Header::~Header()
998 {
999 }
1000
1001 int Header::get_feed_version()
1002 {
1003         return structure->feed_version;
1004 }
1005
1006 Glib::TimeVal Header::get_start_time()
1007 {
1008         return Glib::TimeVal(
1009                 structure->starttime.tv_sec,
1010                 structure->starttime.tv_usec);
1011 }
1012
1013 Meta::Meta(const struct sr_datafeed_meta *structure) :
1014         PacketPayload(),
1015         StructureWrapper<Packet, const struct sr_datafeed_meta>(structure)
1016 {
1017 }
1018
1019 Meta::~Meta()
1020 {
1021 }
1022
1023 map<const ConfigKey *, Glib::VariantBase> Meta::get_config()
1024 {
1025         map<const ConfigKey *, Glib::VariantBase> result;
1026         for (auto l = structure->config; l; l = l->next)
1027         {
1028                 auto config = (struct sr_config *) l->data;
1029                 result[ConfigKey::get(config->key)] = Glib::VariantBase(config->data);
1030         }
1031         return result;
1032 }
1033
1034 Logic::Logic(const struct sr_datafeed_logic *structure) :
1035         PacketPayload(),
1036         StructureWrapper<Packet, const struct sr_datafeed_logic>(structure)
1037 {
1038 }
1039
1040 Logic::~Logic()
1041 {
1042 }
1043
1044 void *Logic::get_data_pointer()
1045 {
1046         return structure->data;
1047 }
1048
1049 size_t Logic::get_data_length()
1050 {
1051         return structure->length;
1052 }
1053
1054 unsigned int Logic::get_unit_size()
1055 {
1056         return structure->unitsize;
1057 }
1058
1059 Analog::Analog(const struct sr_datafeed_analog *structure) :
1060         PacketPayload(),
1061         StructureWrapper<Packet, const struct sr_datafeed_analog>(structure)
1062 {
1063 }
1064
1065 Analog::~Analog()
1066 {
1067 }
1068
1069 float *Analog::get_data_pointer()
1070 {
1071         return structure->data;
1072 }
1073
1074 unsigned int Analog::get_num_samples()
1075 {
1076         return structure->num_samples;
1077 }
1078
1079 vector<shared_ptr<Channel>> Analog::get_channels()
1080 {
1081         vector<shared_ptr<Channel>> result;
1082         for (auto l = structure->channels; l; l = l->next)
1083                 result.push_back(parent->device->get_channel(
1084                         (struct sr_channel *)l->data));
1085         return result;
1086 }
1087
1088 const Quantity *Analog::get_mq()
1089 {
1090         return Quantity::get(structure->mq);
1091 }
1092
1093 const Unit *Analog::get_unit()
1094 {
1095         return Unit::get(structure->unit);
1096 }
1097
1098 vector<const QuantityFlag *> Analog::get_mq_flags()
1099 {
1100         return QuantityFlag::flags_from_mask(structure->mqflags);
1101 }
1102
1103 InputFormat::InputFormat(struct sr_input_format *structure) :
1104         StructureWrapper<Context, struct sr_input_format>(structure)
1105 {
1106 }
1107
1108 InputFormat::~InputFormat()
1109 {
1110 }
1111
1112 string InputFormat::get_name()
1113 {
1114         return valid_string(structure->id);
1115 }
1116
1117 string InputFormat::get_description()
1118 {
1119         return valid_string(structure->description);
1120 }
1121
1122 bool InputFormat::format_match(string filename)
1123 {
1124         return structure->format_match(filename.c_str());
1125 }
1126
1127 shared_ptr<InputFileDevice> InputFormat::open_file(string filename,
1128                 map<string, string> options)
1129 {
1130         auto input = g_new(struct sr_input, 1);
1131         input->param = map_to_hash_string(options);
1132
1133         /** Run initialisation. */
1134         check(structure->init(input, filename.c_str()));
1135
1136         /** Create virtual device. */
1137         return shared_ptr<InputFileDevice>(new InputFileDevice(
1138                 static_pointer_cast<InputFormat>(shared_from_this()), input, filename),
1139                 InputFileDevice::Deleter());
1140 }
1141
1142 InputFileDevice::InputFileDevice(shared_ptr<InputFormat> format,
1143                 struct sr_input *input, string filename) :
1144         Device(input->sdi),
1145         input(input),
1146         format(format),
1147         filename(filename)
1148 {
1149 }
1150
1151 InputFileDevice::~InputFileDevice()
1152 {
1153         g_hash_table_unref(input->param);
1154         g_free(input);
1155 }
1156
1157 void InputFileDevice::load()
1158 {
1159         check(format->structure->loadfile(input, filename.c_str()));
1160 }
1161
1162 Option::Option(const struct sr_option *structure,
1163                 shared_ptr<const struct sr_option> structure_array) :
1164         structure(structure),
1165         structure_array(structure_array)
1166 {
1167 }
1168
1169 Option::~Option()
1170 {
1171 }
1172
1173 string Option::get_id()
1174 {
1175         return valid_string(structure->id);
1176 }
1177
1178 string Option::get_name()
1179 {
1180         return valid_string(structure->name);
1181 }
1182
1183 string Option::get_description()
1184 {
1185         return valid_string(structure->desc);
1186 }
1187
1188 Glib::VariantBase Option::get_default_value()
1189 {
1190         return Glib::VariantBase(structure->def, true);
1191 }
1192
1193 vector<Glib::VariantBase> Option::get_values()
1194 {
1195         vector<Glib::VariantBase> result;
1196         for (auto l = structure->values; l; l = l->next)
1197                 result.push_back(Glib::VariantBase((GVariant *) l->data, true));
1198         return result;
1199 }
1200
1201 OutputFormat::OutputFormat(const struct sr_output_module *structure) :
1202         StructureWrapper<Context, const struct sr_output_module>(structure)
1203 {
1204 }
1205
1206 OutputFormat::~OutputFormat()
1207 {
1208 }
1209
1210 string OutputFormat::get_name()
1211 {
1212         return valid_string(sr_output_id_get(structure));
1213 }
1214
1215 string OutputFormat::get_description()
1216 {
1217         return valid_string(sr_output_description_get(structure));
1218 }
1219
1220 map<string, shared_ptr<Option>> OutputFormat::get_options()
1221 {
1222         const struct sr_option *option = sr_output_options_get(structure);
1223         auto option_array = shared_ptr<const struct sr_option>(
1224                 option, [=](const struct sr_option *) {
1225                         sr_output_options_free(structure); });
1226         map<string, shared_ptr<Option>> result;
1227         for (; option->id; option++)
1228                 result[option->id] = shared_ptr<Option>(
1229                         new Option(option, option_array), Option::Deleter());
1230         return result;
1231 }
1232
1233 shared_ptr<Output> OutputFormat::create_output(
1234         shared_ptr<Device> device, map<string, Glib::VariantBase> options)
1235 {
1236         return shared_ptr<Output>(
1237                 new Output(
1238                         static_pointer_cast<OutputFormat>(shared_from_this()),
1239                                 device, options),
1240                 Output::Deleter());
1241 }
1242
1243 Output::Output(shared_ptr<OutputFormat> format,
1244                 shared_ptr<Device> device, map<string, Glib::VariantBase> options) :
1245         structure(sr_output_new(format->structure,
1246                 map_to_hash_variant(options), device->structure)),
1247         format(format), device(device), options(options)
1248 {
1249 }
1250
1251 Output::~Output()
1252 {
1253         check(sr_output_free(structure));
1254 }
1255
1256 string Output::receive(shared_ptr<Packet> packet)
1257 {
1258         GString *out;
1259         check(sr_output_send(structure, packet->structure, &out));
1260         if (out)
1261         {
1262                 auto result = string(out->str, out->str + out->len);
1263                 g_string_free(out, true);
1264                 return result;
1265         }
1266         else
1267         {
1268                 return string();
1269         }
1270 }
1271
1272 #include "enums.cpp"
1273
1274 }