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