]> sigrok.org Git - pulseview.git/blob - pv/session.cpp
2e98c8f73f40c08a70f451c60716824a1b348bbb
[pulseview.git] / pv / session.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2012-14 Joel Holdsworth <joel@airwebreathe.org.uk>
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 2 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 #ifdef _WIN32
21 // Windows: Avoid boost/thread namespace pollution (which includes windows.h).
22 #define NOGDI
23 #define NORESOURCE
24 #endif
25 #include <boost/thread/locks.hpp>
26 #include <boost/thread/shared_mutex.hpp>
27
28 #include <QFileInfo>
29
30 #include <cassert>
31 #include <mutex>
32 #include <stdexcept>
33
34 #include <sys/stat.h>
35
36 #include "session.hpp"
37 #include "devicemanager.hpp"
38
39 #include "data/analog.hpp"
40 #include "data/analogsegment.hpp"
41 #include "data/decoderstack.hpp"
42 #include "data/logic.hpp"
43 #include "data/logicsegment.hpp"
44 #include "data/signalbase.hpp"
45 #include "data/decode/decoder.hpp"
46
47 #include "devices/hardwaredevice.hpp"
48 #include "devices/inputfile.hpp"
49 #include "devices/sessionfile.hpp"
50
51 #include "toolbars/mainbar.hpp"
52
53 #include "view/analogsignal.hpp"
54 #include "view/decodetrace.hpp"
55 #include "view/logicsignal.hpp"
56 #include "view/signal.hpp"
57 #include "view/view.hpp"
58
59 #include <libsigrokcxx/libsigrokcxx.hpp>
60
61 #ifdef ENABLE_DECODE
62 #include <libsigrokdecode/libsigrokdecode.h>
63 #endif
64
65 using boost::shared_lock;
66 using boost::shared_mutex;
67 using boost::unique_lock;
68
69 using std::dynamic_pointer_cast;
70 using std::function;
71 using std::lock_guard;
72 using std::list;
73 using std::map;
74 using std::mutex;
75 using std::pair;
76 using std::recursive_mutex;
77 using std::set;
78 using std::shared_ptr;
79 using std::string;
80 using std::unordered_set;
81 using std::vector;
82
83 using sigrok::Analog;
84 using sigrok::Channel;
85 using sigrok::ChannelType;
86 using sigrok::ConfigKey;
87 using sigrok::DatafeedCallbackFunction;
88 using sigrok::Error;
89 using sigrok::Header;
90 using sigrok::InputFormat;
91 using sigrok::Logic;
92 using sigrok::Meta;
93 using sigrok::OutputFormat;
94 using sigrok::Packet;
95 using sigrok::PacketPayload;
96 using sigrok::Session;
97 using sigrok::SessionDevice;
98
99 using Glib::VariantBase;
100 using Glib::Variant;
101
102 namespace pv {
103 Session::Session(DeviceManager &device_manager, QString name) :
104         device_manager_(device_manager),
105         default_name_(name),
106         name_(name),
107         capture_state_(Stopped),
108         cur_samplerate_(0)
109 {
110 }
111
112 Session::~Session()
113 {
114         // Stop and join to the thread
115         stop_capture();
116 }
117
118 DeviceManager& Session::device_manager()
119 {
120         return device_manager_;
121 }
122
123 const DeviceManager& Session::device_manager() const
124 {
125         return device_manager_;
126 }
127
128 shared_ptr<sigrok::Session> Session::session() const
129 {
130         if (!device_)
131                 return shared_ptr<sigrok::Session>();
132         return device_->session();
133 }
134
135 shared_ptr<devices::Device> Session::device() const
136 {
137         return device_;
138 }
139
140 QString Session::name() const
141 {
142         return name_;
143 }
144
145 void Session::set_name(QString name)
146 {
147         if (default_name_.isEmpty())
148                 default_name_ = name;
149
150         name_ = name;
151
152         name_changed();
153 }
154
155 const std::list< std::shared_ptr<views::ViewBase> > Session::views() const
156 {
157         return views_;
158 }
159
160 std::shared_ptr<views::ViewBase> Session::main_view() const
161 {
162         return main_view_;
163 }
164
165 void Session::set_main_bar(std::shared_ptr<pv::toolbars::MainBar> main_bar)
166 {
167         main_bar_ = main_bar;
168 }
169
170 shared_ptr<pv::toolbars::MainBar> Session::main_bar() const
171 {
172         return main_bar_;
173 }
174
175 void Session::save_settings(QSettings &settings) const
176 {
177         map<string, string> dev_info;
178         list<string> key_list;
179         int stacks = 0, views = 0;
180
181         if (device_) {
182                 shared_ptr<devices::HardwareDevice> hw_device =
183                         dynamic_pointer_cast< devices::HardwareDevice >(device_);
184
185                 if (hw_device) {
186                         settings.setValue("device_type", "hardware");
187                         settings.beginGroup("device");
188
189                         key_list.push_back("vendor");
190                         key_list.push_back("model");
191                         key_list.push_back("version");
192                         key_list.push_back("serial_num");
193                         key_list.push_back("connection_id");
194
195                         dev_info = device_manager_.get_device_info(device_);
196
197                         for (string key : key_list) {
198                                 if (dev_info.count(key))
199                                         settings.setValue(QString::fromUtf8(key.c_str()),
200                                                         QString::fromUtf8(dev_info.at(key).c_str()));
201                                 else
202                                         settings.remove(QString::fromUtf8(key.c_str()));
203                         }
204
205                         settings.endGroup();
206                 }
207
208                 shared_ptr<devices::SessionFile> sessionfile_device =
209                         dynamic_pointer_cast< devices::SessionFile >(device_);
210
211                 if (sessionfile_device) {
212                         settings.setValue("device_type", "sessionfile");
213                         settings.beginGroup("device");
214                         settings.setValue("filename", QString::fromStdString(
215                                 sessionfile_device->full_name()));
216                         settings.endGroup();
217                 }
218
219                 // Save channels and decoders
220                 for (shared_ptr<data::SignalBase> base : signalbases_) {
221 #ifdef ENABLE_DECODE
222                         if (base->is_decode_signal()) {
223                                 shared_ptr<pv::data::DecoderStack> decoder_stack =
224                                                 base->decoder_stack();
225                                 std::shared_ptr<data::decode::Decoder> top_decoder =
226                                                 decoder_stack->stack().front();
227
228                                 settings.beginGroup("decoder_stack" + QString::number(stacks++));
229                                 settings.setValue("id", top_decoder->decoder()->id);
230                                 settings.setValue("name", top_decoder->decoder()->name);
231                                 settings.endGroup();
232                         } else
233 #endif
234                         {
235                                 settings.beginGroup(base->internal_name());
236                                 base->save_settings(settings);
237                                 settings.endGroup();
238                         }
239                 }
240
241                 settings.setValue("decoder_stacks", stacks);
242
243                 // Save view states and their signal settings
244                 // Note: main_view must be saved as view0
245                 settings.beginGroup("view" + QString::number(views++));
246                 main_view_->save_settings(settings);
247                 settings.endGroup();
248
249                 for (shared_ptr<views::ViewBase> view : views_) {
250                         if (view != main_view_) {
251                                 settings.beginGroup("view" + QString::number(views++));
252                                 view->save_settings(settings);
253                                 settings.endGroup();
254                         }
255                 }
256
257                 settings.setValue("views", views);
258         }
259 }
260
261 void Session::restore_settings(QSettings &settings)
262 {
263         shared_ptr<devices::Device> device;
264
265         QString device_type = settings.value("device_type").toString();
266
267         if (device_type == "hardware") {
268                 map<string, string> dev_info;
269                 list<string> key_list;
270
271                 // Re-select last used device if possible but only if it's not demo
272                 settings.beginGroup("device");
273                 key_list.push_back("vendor");
274                 key_list.push_back("model");
275                 key_list.push_back("version");
276                 key_list.push_back("serial_num");
277                 key_list.push_back("connection_id");
278
279                 for (string key : key_list) {
280                         const QString k = QString::fromStdString(key);
281                         if (!settings.contains(k))
282                                 continue;
283
284                         const string value = settings.value(k).toString().toStdString();
285                         if (!value.empty())
286                                 dev_info.insert(std::make_pair(key, value));
287                 }
288
289                 if (dev_info.count("model") > 0)
290                         device = device_manager_.find_device_from_info(dev_info);
291
292                 if (device)
293                         set_device(device);
294
295                 settings.endGroup();
296         }
297
298         if (device_type == "sessionfile") {
299                 settings.beginGroup("device");
300                 QString filename = settings.value("filename").toString();
301                 settings.endGroup();
302
303                 if (QFileInfo(filename).isReadable()) {
304                         device = std::make_shared<devices::SessionFile>(device_manager_.context(),
305                                 filename.toStdString());
306                         set_device(device);
307
308                         // TODO Perform error handling
309                         start_capture([](QString infoMessage) { (void)infoMessage; });
310
311                         set_name(QFileInfo(filename).fileName());
312                 }
313         }
314
315         if (device) {
316                 // Restore channels
317                 for (shared_ptr<data::SignalBase> base : signalbases_) {
318                         settings.beginGroup(base->internal_name());
319                         base->restore_settings(settings);
320                         settings.endGroup();
321                 }
322
323                 // Restore decoders
324 #ifdef ENABLE_DECODE
325                 int stacks = settings.value("decoder_stacks").toInt();
326
327                 for (int i = 0; i < stacks; i++) {
328                         settings.beginGroup("decoder_stack" + QString::number(i++));
329
330                         QString id = settings.value("id").toString();
331                         add_decoder(srd_decoder_get_by_id(id.toStdString().c_str()));
332
333                         settings.endGroup();
334                 }
335 #endif
336
337                 // Restore views
338                 int views = settings.value("views").toInt();
339
340                 for (int i = 0; i < views; i++) {
341                         settings.beginGroup("view" + QString::number(i));
342
343                         if (i > 0) {
344                                 views::ViewType type = (views::ViewType)settings.value("type").toInt();
345                                 add_view(name_, type, this);
346                                 views_.back()->restore_settings(settings);
347                         } else
348                                 main_view_->restore_settings(settings);
349
350                         settings.endGroup();
351                 }
352         }
353 }
354
355 void Session::select_device(shared_ptr<devices::Device> device)
356 {
357         try {
358                 if (device)
359                         set_device(device);
360                 else
361                         set_default_device();
362         } catch (const QString &e) {
363                 main_bar_->session_error(tr("Failed to Select Device"),
364                         tr("Failed to Select Device"));
365         }
366 }
367
368 void Session::set_device(shared_ptr<devices::Device> device)
369 {
370         assert(device);
371
372         // Ensure we are not capturing before setting the device
373         stop_capture();
374
375         if (device_)
376                 device_->close();
377
378         device_.reset();
379
380         // Revert name back to default name (e.g. "Untitled-1") as the data is gone
381         name_ = default_name_;
382         name_changed();
383
384         // Remove all stored data
385         for (std::shared_ptr<views::ViewBase> view : views_) {
386                 view->clear_signals();
387 #ifdef ENABLE_DECODE
388                 view->clear_decode_signals();
389 #endif
390         }
391         for (const shared_ptr<data::SignalData> d : all_signal_data_)
392                 d->clear();
393         all_signal_data_.clear();
394         signalbases_.clear();
395         cur_logic_segment_.reset();
396
397         for (auto entry : cur_analog_segments_) {
398                 shared_ptr<sigrok::Channel>(entry.first).reset();
399                 shared_ptr<data::AnalogSegment>(entry.second).reset();
400         }
401
402         logic_data_.reset();
403
404         signals_changed();
405
406         device_ = std::move(device);
407
408         try {
409                 device_->open();
410         } catch (const QString &e) {
411                 device_.reset();
412                 device_changed();
413                 throw;
414         }
415
416         device_->session()->add_datafeed_callback([=]
417                 (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
418                         data_feed_in(device, packet);
419                 });
420
421         update_signals();
422         device_changed();
423 }
424
425 void Session::set_default_device()
426 {
427         const list< shared_ptr<devices::HardwareDevice> > &devices =
428                 device_manager_.devices();
429
430         if (devices.empty())
431                 return;
432
433         // Try and find the demo device and select that by default
434         const auto iter = std::find_if(devices.begin(), devices.end(),
435                 [] (const shared_ptr<devices::HardwareDevice> &d) {
436                         return d->hardware_device()->driver()->name() ==
437                         "demo"; });
438         set_device((iter == devices.end()) ? devices.front() : *iter);
439 }
440
441 void Session::load_init_file(const std::string &file_name,
442         const std::string &format)
443 {
444         shared_ptr<InputFormat> input_format;
445
446         if (!format.empty()) {
447                 const map<string, shared_ptr<InputFormat> > formats =
448                         device_manager_.context()->input_formats();
449                 const auto iter = find_if(formats.begin(), formats.end(),
450                         [&](const pair<string, shared_ptr<InputFormat> > f) {
451                                 return f.first == format; });
452                 if (iter == formats.end()) {
453                         main_bar_->session_error(tr("Error"),
454                                 tr("Unexpected input format: %s").arg(QString::fromStdString(format)));
455                         return;
456                 }
457
458                 input_format = (*iter).second;
459         }
460
461         load_file(QString::fromStdString(file_name), input_format);
462 }
463
464 void Session::load_file(QString file_name,
465         std::shared_ptr<sigrok::InputFormat> format,
466         const std::map<std::string, Glib::VariantBase> &options)
467 {
468         const QString errorMessage(
469                 QString("Failed to load file %1").arg(file_name));
470
471         try {
472                 if (format)
473                         set_device(shared_ptr<devices::Device>(
474                                 new devices::InputFile(
475                                         device_manager_.context(),
476                                         file_name.toStdString(),
477                                         format, options)));
478                 else
479                         set_device(shared_ptr<devices::Device>(
480                                 new devices::SessionFile(
481                                         device_manager_.context(),
482                                         file_name.toStdString())));
483         } catch (Error e) {
484                 main_bar_->session_error(tr("Failed to load ") + file_name, e.what());
485                 set_default_device();
486                 main_bar_->update_device_list();
487                 return;
488         }
489
490         main_bar_->update_device_list();
491
492         start_capture([&, errorMessage](QString infoMessage) {
493                 main_bar_->session_error(errorMessage, infoMessage); });
494
495         set_name(QFileInfo(file_name).fileName());
496 }
497
498 Session::capture_state Session::get_capture_state() const
499 {
500         lock_guard<mutex> lock(sampling_mutex_);
501         return capture_state_;
502 }
503
504 void Session::start_capture(function<void (const QString)> error_handler)
505 {
506         if (!device_) {
507                 error_handler(tr("No active device set, can't start acquisition."));
508                 return;
509         }
510
511         stop_capture();
512
513         // Check that at least one channel is enabled
514         const shared_ptr<sigrok::Device> sr_dev = device_->device();
515         if (sr_dev) {
516                 const auto channels = sr_dev->channels();
517                 if (!std::any_of(channels.begin(), channels.end(),
518                         [](shared_ptr<Channel> channel) {
519                                 return channel->enabled(); })) {
520                         error_handler(tr("No channels enabled."));
521                         return;
522                 }
523         }
524
525         // Clear signal data
526         for (const shared_ptr<data::SignalData> d : all_signal_data_)
527                 d->clear();
528
529         // Revert name back to default name (e.g. "Untitled-1") as the data is gone
530         name_ = default_name_;
531         name_changed();
532
533         // Begin the session
534         sampling_thread_ = std::thread(
535                 &Session::sample_thread_proc, this, error_handler);
536 }
537
538 void Session::stop_capture()
539 {
540         if (get_capture_state() != Stopped)
541                 device_->stop();
542
543         // Check that sampling stopped
544         if (sampling_thread_.joinable())
545                 sampling_thread_.join();
546 }
547
548 void Session::register_view(std::shared_ptr<views::ViewBase> view)
549 {
550         if (views_.empty()) {
551                 main_view_ = view;
552         }
553
554         views_.push_back(view);
555
556         update_signals();
557 }
558
559 void Session::deregister_view(std::shared_ptr<views::ViewBase> view)
560 {
561         views_.remove_if([&](std::shared_ptr<views::ViewBase> v) {
562                 return v == view; });
563
564         if (views_.empty()) {
565                 main_view_.reset();
566
567                 // Without a view there can be no main bar
568                 main_bar_.reset();
569         }
570 }
571
572 bool Session::has_view(std::shared_ptr<views::ViewBase> view)
573 {
574         for (std::shared_ptr<views::ViewBase> v : views_)
575                 if (v == view)
576                         return true;
577
578         return false;
579 }
580
581 double Session::get_samplerate() const
582 {
583         double samplerate = 0.0;
584
585         for (const shared_ptr<pv::data::SignalData> d : all_signal_data_) {
586                 assert(d);
587                 const vector< shared_ptr<pv::data::Segment> > segments =
588                         d->segments();
589                 for (const shared_ptr<pv::data::Segment> &s : segments)
590                         samplerate = std::max(samplerate, s->samplerate());
591         }
592         // If there is no sample rate given we use samples as unit
593         if (samplerate == 0.0)
594                 samplerate = 1.0;
595
596         return samplerate;
597 }
598
599 const std::unordered_set< std::shared_ptr<data::SignalBase> >
600         Session::signalbases() const
601 {
602         return signalbases_;
603 }
604
605 #ifdef ENABLE_DECODE
606 bool Session::add_decoder(srd_decoder *const dec)
607 {
608         map<const srd_channel*, shared_ptr<data::SignalBase> > channels;
609         shared_ptr<data::DecoderStack> decoder_stack;
610
611         try {
612                 // Create the decoder
613                 decoder_stack = shared_ptr<data::DecoderStack>(
614                         new data::DecoderStack(*this, dec));
615
616                 // Make a list of all the channels
617                 std::vector<const srd_channel*> all_channels;
618                 for (const GSList *i = dec->channels; i; i = i->next)
619                         all_channels.push_back((const srd_channel*)i->data);
620                 for (const GSList *i = dec->opt_channels; i; i = i->next)
621                         all_channels.push_back((const srd_channel*)i->data);
622
623                 // Auto select the initial channels
624                 for (const srd_channel *pdch : all_channels)
625                         for (shared_ptr<data::SignalBase> b : signalbases_) {
626                                 if (b->type() == ChannelType::LOGIC) {
627                                         if (QString::fromUtf8(pdch->name).toLower().
628                                                 contains(b->name().toLower()))
629                                                 channels[pdch] = b;
630                                 }
631                         }
632
633                 assert(decoder_stack);
634                 assert(!decoder_stack->stack().empty());
635                 assert(decoder_stack->stack().front());
636                 decoder_stack->stack().front()->set_channels(channels);
637
638                 // Create the decode signal
639                 shared_ptr<data::SignalBase> signalbase =
640                         shared_ptr<data::SignalBase>(new data::SignalBase(nullptr));
641
642                 signalbase->set_decoder_stack(decoder_stack);
643                 signalbases_.insert(signalbase);
644
645                 for (std::shared_ptr<views::ViewBase> view : views_)
646                         view->add_decode_signal(signalbase);
647         } catch (std::runtime_error e) {
648                 return false;
649         }
650
651         signals_changed();
652
653         // Do an initial decode
654         decoder_stack->begin_decode();
655
656         return true;
657 }
658
659 void Session::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
660 {
661         signalbases_.erase(signalbase);
662
663         for (std::shared_ptr<views::ViewBase> view : views_)
664                 view->remove_decode_signal(signalbase);
665
666         signals_changed();
667 }
668 #endif
669
670 void Session::set_capture_state(capture_state state)
671 {
672         bool changed;
673
674         {
675                 lock_guard<mutex> lock(sampling_mutex_);
676                 changed = capture_state_ != state;
677                 capture_state_ = state;
678         }
679
680         if (changed)
681                 capture_state_changed(state);
682 }
683
684 void Session::update_signals()
685 {
686         if (!device_) {
687                 signalbases_.clear();
688                 logic_data_.reset();
689                 for (std::shared_ptr<views::ViewBase> view : views_) {
690                         view->clear_signals();
691 #ifdef ENABLE_DECODE
692                         view->clear_decode_signals();
693 #endif
694                 }
695                 return;
696         }
697
698         lock_guard<recursive_mutex> lock(data_mutex_);
699
700         const shared_ptr<sigrok::Device> sr_dev = device_->device();
701         if (!sr_dev) {
702                 signalbases_.clear();
703                 logic_data_.reset();
704                 for (std::shared_ptr<views::ViewBase> view : views_) {
705                         view->clear_signals();
706 #ifdef ENABLE_DECODE
707                         view->clear_decode_signals();
708 #endif
709                 }
710                 return;
711         }
712
713         // Detect what data types we will receive
714         auto channels = sr_dev->channels();
715         unsigned int logic_channel_count = std::count_if(
716                 channels.begin(), channels.end(),
717                 [] (shared_ptr<Channel> channel) {
718                         return channel->type() == ChannelType::LOGIC; });
719
720         // Create data containers for the logic data segments
721         {
722                 lock_guard<recursive_mutex> data_lock(data_mutex_);
723
724                 if (logic_channel_count == 0) {
725                         logic_data_.reset();
726                 } else if (!logic_data_ ||
727                         logic_data_->num_channels() != logic_channel_count) {
728                         logic_data_.reset(new data::Logic(
729                                 logic_channel_count));
730                         assert(logic_data_);
731                 }
732         }
733
734         // Make the signals list
735         for (std::shared_ptr<views::ViewBase> viewbase : views_) {
736                 views::TraceView::View *trace_view =
737                         qobject_cast<views::TraceView::View*>(viewbase.get());
738
739                 if (trace_view) {
740                         unordered_set< shared_ptr<views::TraceView::Signal> >
741                                 prev_sigs(trace_view->signals());
742                         trace_view->clear_signals();
743
744                         for (auto channel : sr_dev->channels()) {
745                                 shared_ptr<data::SignalBase> signalbase;
746                                 shared_ptr<views::TraceView::Signal> signal;
747
748                                 // Find the channel in the old signals
749                                 const auto iter = std::find_if(
750                                         prev_sigs.cbegin(), prev_sigs.cend(),
751                                         [&](const shared_ptr<views::TraceView::Signal> &s) {
752                                                 return s->base()->channel() == channel;
753                                         });
754                                 if (iter != prev_sigs.end()) {
755                                         // Copy the signal from the old set to the new
756                                         signal = *iter;
757                                         trace_view->add_signal(signal);
758                                 } else {
759                                         // Find the signalbase for this channel if possible
760                                         signalbase.reset();
761                                         for (const shared_ptr<data::SignalBase> b : signalbases_)
762                                                 if (b->channel() == channel)
763                                                         signalbase = b;
764
765                                         switch(channel->type()->id()) {
766                                         case SR_CHANNEL_LOGIC:
767                                                 if (!signalbase) {
768                                                         signalbase = shared_ptr<data::SignalBase>(
769                                                                 new data::SignalBase(channel));
770                                                         signalbases_.insert(signalbase);
771
772                                                         all_signal_data_.insert(logic_data_);
773                                                         signalbase->set_data(logic_data_);
774                                                 }
775
776                                                 signal = shared_ptr<views::TraceView::Signal>(
777                                                         new views::TraceView::LogicSignal(*this,
778                                                                 device_, signalbase));
779                                                 trace_view->add_signal(signal);
780                                                 break;
781
782                                         case SR_CHANNEL_ANALOG:
783                                         {
784                                                 if (!signalbase) {
785                                                         signalbase = shared_ptr<data::SignalBase>(
786                                                                 new data::SignalBase(channel));
787                                                         signalbases_.insert(signalbase);
788
789                                                         shared_ptr<data::Analog> data(new data::Analog());
790                                                         all_signal_data_.insert(data);
791                                                         signalbase->set_data(data);
792                                                 }
793
794                                                 signal = shared_ptr<views::TraceView::Signal>(
795                                                         new views::TraceView::AnalogSignal(
796                                                                 *this, signalbase));
797                                                 trace_view->add_signal(signal);
798                                                 break;
799                                         }
800
801                                         default:
802                                                 assert(0);
803                                                 break;
804                                         }
805                                 }
806                         }
807                 }
808         }
809
810         signals_changed();
811 }
812
813 shared_ptr<data::SignalBase> Session::signalbase_from_channel(
814         shared_ptr<sigrok::Channel> channel) const
815 {
816         for (shared_ptr<data::SignalBase> sig : signalbases_) {
817                 assert(sig);
818                 if (sig->channel() == channel)
819                         return sig;
820         }
821         return shared_ptr<data::SignalBase>();
822 }
823
824 void Session::sample_thread_proc(function<void (const QString)> error_handler)
825 {
826         assert(error_handler);
827
828         if (!device_)
829                 return;
830
831         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
832
833         out_of_memory_ = false;
834
835         try {
836                 device_->start();
837         } catch (Error e) {
838                 error_handler(e.what());
839                 return;
840         }
841
842         set_capture_state(device_->session()->trigger() ?
843                 AwaitingTrigger : Running);
844
845         device_->run();
846         set_capture_state(Stopped);
847
848         // Confirm that SR_DF_END was received
849         if (cur_logic_segment_) {
850                 qDebug("SR_DF_END was not received.");
851                 assert(0);
852         }
853
854         if (out_of_memory_)
855                 error_handler(tr("Out of memory, acquisition stopped."));
856 }
857
858 void Session::feed_in_header()
859 {
860         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
861 }
862
863 void Session::feed_in_meta(shared_ptr<Meta> meta)
864 {
865         for (auto entry : meta->config()) {
866                 switch (entry.first->id()) {
867                 case SR_CONF_SAMPLERATE:
868                         // We can't rely on the header to always contain the sample rate,
869                         // so in case it's supplied via a meta packet, we use it.
870                         if (!cur_samplerate_)
871                                 cur_samplerate_ = g_variant_get_uint64(entry.second.gobj());
872
873                         /// @todo handle samplerate changes
874                         break;
875                 default:
876                         // Unknown metadata is not an error.
877                         break;
878                 }
879         }
880
881         signals_changed();
882 }
883
884 void Session::feed_in_trigger()
885 {
886         // The channel containing most samples should be most accurate
887         uint64_t sample_count = 0;
888
889         {
890                 for (const shared_ptr<pv::data::SignalData> d : all_signal_data_) {
891                         assert(d);
892                         uint64_t temp_count = 0;
893
894                         const vector< shared_ptr<pv::data::Segment> > segments =
895                                 d->segments();
896                         for (const shared_ptr<pv::data::Segment> &s : segments)
897                                 temp_count += s->get_sample_count();
898
899                         if (temp_count > sample_count)
900                                 sample_count = temp_count;
901                 }
902         }
903
904         trigger_event(sample_count / get_samplerate());
905 }
906
907 void Session::feed_in_frame_begin()
908 {
909         if (cur_logic_segment_ || !cur_analog_segments_.empty())
910                 frame_began();
911 }
912
913 void Session::feed_in_logic(shared_ptr<Logic> logic)
914 {
915         lock_guard<recursive_mutex> lock(data_mutex_);
916
917         const size_t sample_count = logic->data_length() / logic->unit_size();
918
919         if (!logic_data_) {
920                 // The only reason logic_data_ would not have been created is
921                 // if it was not possible to determine the signals when the
922                 // device was created.
923                 update_signals();
924         }
925
926         if (!cur_logic_segment_) {
927                 // This could be the first packet after a trigger
928                 set_capture_state(Running);
929
930                 // Create a new data segment
931                 cur_logic_segment_ = shared_ptr<data::LogicSegment>(
932                         new data::LogicSegment(
933                                 logic, cur_samplerate_, sample_count));
934                 logic_data_->push_segment(cur_logic_segment_);
935
936                 // @todo Putting this here means that only listeners querying
937                 // for logic will be notified. Currently the only user of
938                 // frame_began is DecoderStack, but in future we need to signal
939                 // this after both analog and logic sweeps have begun.
940                 frame_began();
941         } else {
942                 // Append to the existing data segment
943                 cur_logic_segment_->append_payload(logic);
944         }
945
946         data_received();
947 }
948
949 void Session::feed_in_analog(shared_ptr<Analog> analog)
950 {
951         lock_guard<recursive_mutex> lock(data_mutex_);
952
953         const vector<shared_ptr<Channel>> channels = analog->channels();
954         const unsigned int channel_count = channels.size();
955         const size_t sample_count = analog->num_samples() / channel_count;
956         const float *data = static_cast<const float *>(analog->data_pointer());
957         bool sweep_beginning = false;
958
959         if (signalbases_.empty())
960                 update_signals();
961
962         for (auto channel : channels) {
963                 shared_ptr<data::AnalogSegment> segment;
964
965                 // Try to get the segment of the channel
966                 const map< shared_ptr<Channel>, shared_ptr<data::AnalogSegment> >::
967                         iterator iter = cur_analog_segments_.find(channel);
968                 if (iter != cur_analog_segments_.end())
969                         segment = (*iter).second;
970                 else {
971                         // If no segment was found, this means we haven't
972                         // created one yet. i.e. this is the first packet
973                         // in the sweep containing this segment.
974                         sweep_beginning = true;
975
976                         // Create a segment, keep it in the maps of channels
977                         segment = shared_ptr<data::AnalogSegment>(
978                                 new data::AnalogSegment(
979                                         cur_samplerate_, sample_count));
980                         cur_analog_segments_[channel] = segment;
981
982                         // Find the analog data associated with the channel
983                         shared_ptr<data::SignalBase> base = signalbase_from_channel(channel);
984                         assert(base);
985
986                         shared_ptr<data::Analog> data(base->analog_data());
987                         assert(data);
988
989                         // Push the segment into the analog data.
990                         data->push_segment(segment);
991                 }
992
993                 assert(segment);
994
995                 // Append the samples in the segment
996                 segment->append_interleaved_samples(data++, sample_count,
997                         channel_count);
998         }
999
1000         if (sweep_beginning) {
1001                 // This could be the first packet after a trigger
1002                 set_capture_state(Running);
1003         }
1004
1005         data_received();
1006 }
1007
1008 void Session::data_feed_in(shared_ptr<sigrok::Device> device,
1009         shared_ptr<Packet> packet)
1010 {
1011         (void)device;
1012
1013         assert(device);
1014         assert(device == device_->device());
1015         assert(packet);
1016
1017         switch (packet->type()->id()) {
1018         case SR_DF_HEADER:
1019                 feed_in_header();
1020                 break;
1021
1022         case SR_DF_META:
1023                 feed_in_meta(dynamic_pointer_cast<Meta>(packet->payload()));
1024                 break;
1025
1026         case SR_DF_TRIGGER:
1027                 feed_in_trigger();
1028                 break;
1029
1030         case SR_DF_FRAME_BEGIN:
1031                 feed_in_frame_begin();
1032                 break;
1033
1034         case SR_DF_LOGIC:
1035                 try {
1036                         feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
1037                 } catch (std::bad_alloc) {
1038                         out_of_memory_ = true;
1039                         device_->stop();
1040                 }
1041                 break;
1042
1043         case SR_DF_ANALOG:
1044                 try {
1045                         feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
1046                 } catch (std::bad_alloc) {
1047                         out_of_memory_ = true;
1048                         device_->stop();
1049                 }
1050                 break;
1051
1052         case SR_DF_END:
1053         {
1054                 {
1055                         lock_guard<recursive_mutex> lock(data_mutex_);
1056                         cur_logic_segment_.reset();
1057                         cur_analog_segments_.clear();
1058                 }
1059                 frame_ended();
1060                 break;
1061         }
1062         default:
1063                 break;
1064         }
1065 }
1066
1067 } // namespace pv