]> sigrok.org Git - pulseview.git/blob - pv/session.cpp
Session: Use ordered container to preserve DecodeTrace order
[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 #include <cassert>
21 #include <memory>
22 #include <mutex>
23 #include <stdexcept>
24
25 #include <sys/stat.h>
26
27 #include <QDebug>
28 #include <QFileInfo>
29
30 #include "devicemanager.hpp"
31 #include "mainwindow.hpp"
32 #include "session.hpp"
33 #include "util.hpp"
34
35 #include "data/analog.hpp"
36 #include "data/analogsegment.hpp"
37 #include "data/decode/decoder.hpp"
38 #include "data/logic.hpp"
39 #include "data/logicsegment.hpp"
40 #include "data/signalbase.hpp"
41
42 #include "devices/hardwaredevice.hpp"
43 #include "devices/inputfile.hpp"
44 #include "devices/sessionfile.hpp"
45
46 #include "toolbars/mainbar.hpp"
47
48 #include "views/trace/analogsignal.hpp"
49 #include "views/trace/decodetrace.hpp"
50 #include "views/trace/logicsignal.hpp"
51 #include "views/trace/signal.hpp"
52 #include "views/trace/view.hpp"
53
54 #include <libsigrokcxx/libsigrokcxx.hpp>
55
56 #ifdef ENABLE_FLOW
57 #include <gstreamermm.h>
58 #include <libsigrokflow/libsigrokflow.hpp>
59 #endif
60
61 #ifdef ENABLE_DECODE
62 #include <libsigrokdecode/libsigrokdecode.h>
63 #include "data/decodesignal.hpp"
64 #endif
65
66 using std::bad_alloc;
67 using std::dynamic_pointer_cast;
68 using std::find_if;
69 using std::function;
70 using std::list;
71 using std::lock_guard;
72 using std::make_pair;
73 using std::make_shared;
74 using std::map;
75 using std::max;
76 using std::move;
77 using std::mutex;
78 using std::pair;
79 using std::recursive_mutex;
80 using std::runtime_error;
81 using std::shared_ptr;
82 using std::string;
83 #ifdef ENABLE_FLOW
84 using std::unique_lock;
85 #endif
86 using std::unique_ptr;
87 using std::unordered_set;
88 using std::vector;
89
90 using sigrok::Analog;
91 using sigrok::Channel;
92 using sigrok::ConfigKey;
93 using sigrok::DatafeedCallbackFunction;
94 using sigrok::Error;
95 using sigrok::InputFormat;
96 using sigrok::Logic;
97 using sigrok::Meta;
98 using sigrok::Packet;
99 using sigrok::Session;
100
101 using Glib::VariantBase;
102
103 #ifdef ENABLE_FLOW
104 using Gst::Bus;
105 using Gst::ElementFactory;
106 using Gst::Pipeline;
107 #endif
108
109 using pv::util::Timestamp;
110 using pv::views::trace::Signal;
111 using pv::views::trace::AnalogSignal;
112 using pv::views::trace::LogicSignal;
113
114 namespace pv {
115
116 shared_ptr<sigrok::Context> Session::sr_context;
117
118 Session::Session(DeviceManager &device_manager, QString name) :
119         device_manager_(device_manager),
120         default_name_(name),
121         name_(name),
122         capture_state_(Stopped),
123         cur_samplerate_(0),
124         data_saved_(true)
125 {
126 }
127
128 Session::~Session()
129 {
130         // Stop and join to the thread
131         stop_capture();
132 }
133
134 DeviceManager& Session::device_manager()
135 {
136         return device_manager_;
137 }
138
139 const DeviceManager& Session::device_manager() const
140 {
141         return device_manager_;
142 }
143
144 shared_ptr<sigrok::Session> Session::session() const
145 {
146         if (!device_)
147                 return shared_ptr<sigrok::Session>();
148         return device_->session();
149 }
150
151 shared_ptr<devices::Device> Session::device() const
152 {
153         return device_;
154 }
155
156 QString Session::name() const
157 {
158         return name_;
159 }
160
161 void Session::set_name(QString name)
162 {
163         if (default_name_.isEmpty())
164                 default_name_ = name;
165
166         name_ = name;
167
168         name_changed();
169 }
170
171 const vector< shared_ptr<views::ViewBase> > Session::views() const
172 {
173         return views_;
174 }
175
176 shared_ptr<views::ViewBase> Session::main_view() const
177 {
178         return main_view_;
179 }
180
181 void Session::set_main_bar(shared_ptr<pv::toolbars::MainBar> main_bar)
182 {
183         main_bar_ = main_bar;
184 }
185
186 shared_ptr<pv::toolbars::MainBar> Session::main_bar() const
187 {
188         return main_bar_;
189 }
190
191 bool Session::data_saved() const
192 {
193         return data_saved_;
194 }
195
196 void Session::save_setup(QSettings &settings) const
197 {
198         int i = 0;
199
200         // Save channels and decoders
201         for (const shared_ptr<data::SignalBase>& base : signalbases_) {
202 #ifdef ENABLE_DECODE
203                 if (base->is_decode_signal()) {
204                         settings.beginGroup("decode_signal" + QString::number(i++));
205                         base->save_settings(settings);
206                         settings.endGroup();
207                 } else
208 #endif
209                 {
210                         settings.beginGroup(base->internal_name());
211                         base->save_settings(settings);
212                         settings.endGroup();
213                 }
214         }
215
216         settings.setValue("decode_signals", i);
217
218         // Save view states and their signal settings
219         // Note: main_view must be saved as view0
220         i = 0;
221         settings.beginGroup("view" + QString::number(i++));
222         main_view_->save_settings(settings);
223         settings.endGroup();
224
225         for (const shared_ptr<views::ViewBase>& view : views_) {
226                 if (view != main_view_) {
227                         settings.beginGroup("view" + QString::number(i++));
228                         settings.setValue("type", view->get_type());
229                         view->save_settings(settings);
230                         settings.endGroup();
231                 }
232         }
233
234         settings.setValue("views", i);
235
236         int view_id = 0;
237         i = 0;
238         for (const shared_ptr<views::ViewBase> vb : views_) {
239                 shared_ptr<views::trace::View> tv = dynamic_pointer_cast<views::trace::View>(vb);
240                 if (tv) {
241                         for (const shared_ptr<views::trace::TimeItem>& time_item : tv->time_items()) {
242
243                                 const shared_ptr<views::trace::Flag> flag =
244                                         dynamic_pointer_cast<views::trace::Flag>(time_item);
245                                 if (flag) {
246                                         if (!flag->enabled())
247                                                 continue;
248
249                                         settings.beginGroup("meta_obj" + QString::number(i++));
250                                         settings.setValue("type", "time_marker");
251                                         settings.setValue("assoc_view", view_id);
252                                         GlobalSettings::store_timestamp(settings, "time", flag->time());
253                                         settings.setValue("text", flag->get_text());
254                                         settings.endGroup();
255                                 }
256                         }
257
258                         if (tv->cursors_shown()) {
259                                 settings.beginGroup("meta_obj" + QString::number(i++));
260                                 settings.setValue("type", "selection");
261                                 settings.setValue("assoc_view", view_id);
262                                 const shared_ptr<views::trace::CursorPair> cp = tv->cursors();
263                                 GlobalSettings::store_timestamp(settings, "start_time", cp->first()->time());
264                                 GlobalSettings::store_timestamp(settings, "end_time", cp->second()->time());
265                                 settings.endGroup();
266                         }
267                 }
268
269                 view_id++;
270         }
271
272         settings.setValue("meta_objs", i);
273 }
274
275 void Session::save_settings(QSettings &settings) const
276 {
277         map<string, string> dev_info;
278         list<string> key_list;
279
280         if (device_) {
281                 shared_ptr<devices::HardwareDevice> hw_device =
282                         dynamic_pointer_cast< devices::HardwareDevice >(device_);
283
284                 if (hw_device) {
285                         settings.setValue("device_type", "hardware");
286                         settings.beginGroup("device");
287
288                         key_list.emplace_back("vendor");
289                         key_list.emplace_back("model");
290                         key_list.emplace_back("version");
291                         key_list.emplace_back("serial_num");
292                         key_list.emplace_back("connection_id");
293
294                         dev_info = device_manager_.get_device_info(device_);
295
296                         for (string& key : key_list) {
297                                 if (dev_info.count(key))
298                                         settings.setValue(QString::fromUtf8(key.c_str()),
299                                                         QString::fromUtf8(dev_info.at(key).c_str()));
300                                 else
301                                         settings.remove(QString::fromUtf8(key.c_str()));
302                         }
303
304                         settings.endGroup();
305                 }
306
307                 shared_ptr<devices::SessionFile> sessionfile_device =
308                         dynamic_pointer_cast<devices::SessionFile>(device_);
309
310                 if (sessionfile_device) {
311                         settings.setValue("device_type", "sessionfile");
312                         settings.beginGroup("device");
313                         settings.setValue("filename", QString::fromStdString(
314                                 sessionfile_device->full_name()));
315                         settings.endGroup();
316                 }
317
318                 shared_ptr<devices::InputFile> inputfile_device =
319                         dynamic_pointer_cast<devices::InputFile>(device_);
320
321                 if (inputfile_device) {
322                         settings.setValue("device_type", "inputfile");
323                         settings.beginGroup("device");
324                         inputfile_device->save_meta_to_settings(settings);
325                         settings.endGroup();
326                 }
327
328                 save_setup(settings);
329         }
330 }
331
332 void Session::restore_setup(QSettings &settings)
333 {
334         // Restore channels
335         for (shared_ptr<data::SignalBase> base : signalbases_) {
336                 settings.beginGroup(base->internal_name());
337                 base->restore_settings(settings);
338                 settings.endGroup();
339         }
340
341         // Restore decoders
342 #ifdef ENABLE_DECODE
343         int decode_signals = settings.value("decode_signals").toInt();
344
345         for (int i = 0; i < decode_signals; i++) {
346                 settings.beginGroup("decode_signal" + QString::number(i));
347                 shared_ptr<data::DecodeSignal> signal = add_decode_signal();
348                 signal->restore_settings(settings);
349                 settings.endGroup();
350         }
351 #endif
352
353         // Restore views
354         int views = settings.value("views").toInt();
355
356         for (int i = 0; i < views; i++) {
357                 settings.beginGroup("view" + QString::number(i));
358
359                 if (i > 0) {
360                         views::ViewType type = (views::ViewType)settings.value("type").toInt();
361                         add_view(type, this);
362                         views_.back()->restore_settings(settings);
363                 } else
364                         main_view_->restore_settings(settings);
365
366                 settings.endGroup();
367         }
368
369         // Restore meta objects like markers and cursors
370         int meta_objs = settings.value("meta_objs").toInt();
371
372         for (int i = 0; i < meta_objs; i++) {
373                 settings.beginGroup("meta_obj" + QString::number(i));
374
375                 shared_ptr<views::ViewBase> vb;
376                 shared_ptr<views::trace::View> tv;
377                 if (settings.contains("assoc_view"))
378                         vb = views_.at(settings.value("assoc_view").toInt());
379
380                 if (vb)
381                         tv = dynamic_pointer_cast<views::trace::View>(vb);
382
383                 const QString type = settings.value("type").toString();
384
385                 if ((type == "time_marker") && tv) {
386                         Timestamp ts = GlobalSettings::restore_timestamp(settings, "time");
387                         shared_ptr<views::trace::Flag> flag = tv->add_flag(ts);
388                         flag->set_text(settings.value("text").toString());
389                 }
390
391                 if ((type == "selection") && tv) {
392                         Timestamp start = GlobalSettings::restore_timestamp(settings, "start_time");
393                         Timestamp end = GlobalSettings::restore_timestamp(settings, "end_time");
394                         tv->set_cursors(start, end);
395                         tv->show_cursors();
396                 }
397
398                 settings.endGroup();
399         }
400 }
401
402 void Session::restore_settings(QSettings &settings)
403 {
404         shared_ptr<devices::Device> device;
405
406         const QString device_type = settings.value("device_type").toString();
407
408         if (device_type == "hardware") {
409                 map<string, string> dev_info;
410                 list<string> key_list;
411
412                 // Re-select last used device if possible but only if it's not demo
413                 settings.beginGroup("device");
414                 key_list.emplace_back("vendor");
415                 key_list.emplace_back("model");
416                 key_list.emplace_back("version");
417                 key_list.emplace_back("serial_num");
418                 key_list.emplace_back("connection_id");
419
420                 for (string key : key_list) {
421                         const QString k = QString::fromStdString(key);
422                         if (!settings.contains(k))
423                                 continue;
424
425                         const string value = settings.value(k).toString().toStdString();
426                         if (!value.empty())
427                                 dev_info.insert(make_pair(key, value));
428                 }
429
430                 if (dev_info.count("model") > 0)
431                         device = device_manager_.find_device_from_info(dev_info);
432
433                 if (device)
434                         set_device(device);
435
436                 settings.endGroup();
437         }
438
439         if ((device_type == "sessionfile") || (device_type == "inputfile")) {
440                 if (device_type == "sessionfile") {
441                         settings.beginGroup("device");
442                         const QString filename = settings.value("filename").toString();
443                         settings.endGroup();
444
445                         if (QFileInfo(filename).isReadable()) {
446                                 device = make_shared<devices::SessionFile>(device_manager_.context(),
447                                         filename.toStdString());
448                         }
449                 }
450
451                 if (device_type == "inputfile") {
452                         settings.beginGroup("device");
453                         device = make_shared<devices::InputFile>(device_manager_.context(),
454                                 settings);
455                         settings.endGroup();
456                 }
457
458                 if (device) {
459                         set_device(device);
460
461                         start_capture([](QString infoMessage) {
462                                 // TODO Emulate noquote()
463                                 qDebug() << "Session error:" << infoMessage; });
464
465                         set_name(QString::fromStdString(
466                                 dynamic_pointer_cast<devices::File>(device)->display_name(device_manager_)));
467                 }
468         }
469
470         if (device)
471                 restore_setup(settings);
472 }
473
474 void Session::select_device(shared_ptr<devices::Device> device)
475 {
476         try {
477                 if (device)
478                         set_device(device);
479                 else
480                         set_default_device();
481         } catch (const QString &e) {
482                 MainWindow::show_session_error(tr("Failed to select device"), e);
483         }
484 }
485
486 void Session::set_device(shared_ptr<devices::Device> device)
487 {
488         assert(device);
489
490         // Ensure we are not capturing before setting the device
491         stop_capture();
492
493         if (device_)
494                 device_->close();
495
496         device_.reset();
497
498         // Revert name back to default name (e.g. "Session 1") as the data is gone
499         name_ = default_name_;
500         name_changed();
501
502         // Remove all stored data and reset all views
503         for (shared_ptr<views::ViewBase> view : views_) {
504                 view->clear_signals();
505 #ifdef ENABLE_DECODE
506                 view->clear_decode_signals();
507 #endif
508                 view->reset_view_state();
509         }
510         for (const shared_ptr<data::SignalData>& d : all_signal_data_)
511                 d->clear();
512         all_signal_data_.clear();
513         signalbases_.clear();
514         cur_logic_segment_.reset();
515
516         for (auto& entry : cur_analog_segments_) {
517                 shared_ptr<sigrok::Channel>(entry.first).reset();
518                 shared_ptr<data::AnalogSegment>(entry.second).reset();
519         }
520
521         logic_data_.reset();
522
523         signals_changed();
524
525         device_ = move(device);
526
527         try {
528                 device_->open();
529         } catch (const QString &e) {
530                 device_.reset();
531                 MainWindow::show_session_error(tr("Failed to open device"), e);
532         }
533
534         if (device_) {
535                 device_->session()->add_datafeed_callback([=]
536                         (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
537                                 data_feed_in(device, packet);
538                         });
539
540                 update_signals();
541         }
542
543         device_changed();
544 }
545
546 void Session::set_default_device()
547 {
548         const list< shared_ptr<devices::HardwareDevice> > &devices =
549                 device_manager_.devices();
550
551         if (devices.empty())
552                 return;
553
554         // Try and find the demo device and select that by default
555         const auto iter = find_if(devices.begin(), devices.end(),
556                 [] (const shared_ptr<devices::HardwareDevice> &d) {
557                         return d->hardware_device()->driver()->name() == "demo"; });
558         set_device((iter == devices.end()) ? devices.front() : *iter);
559 }
560
561 bool Session::using_file_device() const
562 {
563         shared_ptr<devices::SessionFile> sessionfile_device =
564                 dynamic_pointer_cast<devices::SessionFile>(device_);
565
566         shared_ptr<devices::InputFile> inputfile_device =
567                 dynamic_pointer_cast<devices::InputFile>(device_);
568
569         return (sessionfile_device || inputfile_device);
570 }
571
572 /**
573  * Convert generic options to data types that are specific to InputFormat.
574  *
575  * @param[in] user_spec Vector of tokenized words, string format.
576  * @param[in] fmt_opts Input format's options, result of InputFormat::options().
577  *
578  * @return Map of options suitable for InputFormat::create_input().
579  */
580 map<string, Glib::VariantBase>
581 Session::input_format_options(vector<string> user_spec,
582                 map<string, shared_ptr<Option>> fmt_opts)
583 {
584         map<string, Glib::VariantBase> result;
585
586         for (auto& entry : user_spec) {
587                 /*
588                  * Split key=value specs. Accept entries without separator
589                  * (for simplified boolean specifications).
590                  */
591                 string key, val;
592                 size_t pos = entry.find("=");
593                 if (pos == std::string::npos) {
594                         key = entry;
595                         val = "";
596                 } else {
597                         key = entry.substr(0, pos);
598                         val = entry.substr(pos + 1);
599                 }
600
601                 /*
602                  * Skip user specifications that are not a member of the
603                  * format's set of supported options. Have the text input
604                  * spec converted to the required input format specific
605                  * data type.
606                  */
607                 auto found = fmt_opts.find(key);
608                 if (found == fmt_opts.end())
609                         continue;
610                 shared_ptr<Option> opt = found->second;
611                 result[key] = opt->parse_string(val);
612         }
613
614         return result;
615 }
616
617 void Session::load_init_file(const string &file_name,
618         const string &format, const string &setup_file_name)
619 {
620         shared_ptr<InputFormat> input_format;
621         map<string, Glib::VariantBase> input_opts;
622
623         if (!format.empty()) {
624                 const map<string, shared_ptr<InputFormat> > formats =
625                         device_manager_.context()->input_formats();
626                 auto user_opts = pv::util::split_string(format, ":");
627                 string user_name = user_opts.front();
628                 user_opts.erase(user_opts.begin());
629                 const auto iter = find_if(formats.begin(), formats.end(),
630                         [&](const pair<string, shared_ptr<InputFormat> > f) {
631                                 return f.first == user_name; });
632                 if (iter == formats.end()) {
633                         MainWindow::show_session_error(tr("Error"),
634                                 tr("Unexpected input format: %s").arg(QString::fromStdString(format)));
635                         return;
636                 }
637                 input_format = (*iter).second;
638                 input_opts = input_format_options(user_opts,
639                         input_format->options());
640         }
641
642         load_file(QString::fromStdString(file_name), QString::fromStdString(setup_file_name),
643                 input_format, input_opts);
644 }
645
646 void Session::load_file(QString file_name, QString setup_file_name,
647         shared_ptr<sigrok::InputFormat> format, const map<string, Glib::VariantBase> &options)
648 {
649         const QString errorMessage(
650                 QString("Failed to load file %1").arg(file_name));
651
652         // In the absence of a caller's format spec, try to auto detect.
653         // Assume "sigrok session file" upon lookup miss.
654         if (!format)
655                 format = device_manager_.context()->input_format_match(file_name.toStdString());
656         try {
657                 if (format)
658                         set_device(shared_ptr<devices::Device>(
659                                 new devices::InputFile(
660                                         device_manager_.context(),
661                                         file_name.toStdString(),
662                                         format, options)));
663                 else
664                         set_device(shared_ptr<devices::Device>(
665                                 new devices::SessionFile(
666                                         device_manager_.context(),
667                                         file_name.toStdString())));
668         } catch (Error& e) {
669                 MainWindow::show_session_error(tr("Failed to load %1").arg(file_name), e.what());
670                 set_default_device();
671                 main_bar_->update_device_list();
672                 return;
673         }
674
675         // Use the input file with .pvs extension if no setup file was given
676         if (setup_file_name.isEmpty()) {
677                 setup_file_name = file_name;
678                 setup_file_name.truncate(setup_file_name.lastIndexOf('.'));
679                 setup_file_name.append(".pvs");
680         }
681
682         if (QFileInfo::exists(setup_file_name) && QFileInfo(setup_file_name).isReadable()) {
683                 QSettings settings_storage(setup_file_name, QSettings::IniFormat);
684                 restore_setup(settings_storage);
685         }
686
687         main_bar_->update_device_list();
688
689         start_capture([&, errorMessage](QString infoMessage) {
690                 MainWindow::show_session_error(errorMessage, infoMessage); });
691
692         set_name(QFileInfo(file_name).fileName());
693 }
694
695 Session::capture_state Session::get_capture_state() const
696 {
697         lock_guard<mutex> lock(sampling_mutex_);
698         return capture_state_;
699 }
700
701 void Session::start_capture(function<void (const QString)> error_handler)
702 {
703         if (!device_) {
704                 error_handler(tr("No active device set, can't start acquisition."));
705                 return;
706         }
707
708         stop_capture();
709
710         // Check that at least one channel is enabled
711         const shared_ptr<sigrok::Device> sr_dev = device_->device();
712         if (sr_dev) {
713                 const auto channels = sr_dev->channels();
714                 if (!any_of(channels.begin(), channels.end(),
715                         [](shared_ptr<Channel> channel) {
716                                 return channel->enabled(); })) {
717                         error_handler(tr("No channels enabled."));
718                         return;
719                 }
720         }
721
722         // Clear signal data
723         for (const shared_ptr<data::SignalData>& d : all_signal_data_)
724                 d->clear();
725
726         trigger_list_.clear();
727
728         // Revert name back to default name (e.g. "Session 1") for real devices
729         // as the (possibly saved) data is gone. File devices keep their name.
730         shared_ptr<devices::HardwareDevice> hw_device =
731                 dynamic_pointer_cast< devices::HardwareDevice >(device_);
732
733         if (hw_device) {
734                 name_ = default_name_;
735                 name_changed();
736         }
737
738         // Begin the session
739         sampling_thread_ = std::thread(
740                 &Session::sample_thread_proc, this, error_handler);
741 }
742
743 void Session::stop_capture()
744 {
745         if (get_capture_state() != Stopped)
746                 device_->stop();
747
748         // Check that sampling stopped
749         if (sampling_thread_.joinable())
750                 sampling_thread_.join();
751 }
752
753 void Session::register_view(shared_ptr<views::ViewBase> view)
754 {
755         if (views_.empty())
756                 main_view_ = view;
757
758         views_.push_back(view);
759
760         // Add all device signals
761         update_signals();
762
763         // Add all other signals
764         unordered_set< shared_ptr<data::SignalBase> > view_signalbases = view->signalbases();
765
766         for (const shared_ptr<data::SignalBase>& signalbase : signalbases_) {
767                 const int sb_exists = count_if(
768                         view_signalbases.cbegin(), view_signalbases.cend(),
769                         [&](const shared_ptr<data::SignalBase> &sb) {
770                                 return sb == signalbase;
771                         });
772
773                 // Add the signal to the view if it doesn't have it yet
774                 if (!sb_exists)
775                         switch (signalbase->type()) {
776                         case data::SignalBase::AnalogChannel:
777                         case data::SignalBase::LogicChannel:
778                         case data::SignalBase::MathChannel:
779                                 view->add_signalbase(signalbase);
780                                 break;
781                         case data::SignalBase::DecodeChannel:
782 #ifdef ENABLE_DECODE
783                                 view->add_decode_signal(dynamic_pointer_cast<data::DecodeSignal>(signalbase));
784 #endif
785                                 break;
786                         }
787         }
788
789         signals_changed();
790 }
791
792 void Session::deregister_view(shared_ptr<views::ViewBase> view)
793 {
794         views_.erase(std::remove_if(views_.begin(), views_.end(),
795                 [&](shared_ptr<views::ViewBase> v) { return v == view; }),
796                 views_.end());
797
798         if (views_.empty()) {
799                 main_view_.reset();
800
801                 // Without a view there can be no main bar
802                 main_bar_.reset();
803         }
804 }
805
806 bool Session::has_view(shared_ptr<views::ViewBase> view)
807 {
808         for (shared_ptr<views::ViewBase>& v : views_)
809                 if (v == view)
810                         return true;
811
812         return false;
813 }
814
815 double Session::get_samplerate() const
816 {
817         double samplerate = 0.0;
818
819         for (const shared_ptr<pv::data::SignalData>& d : all_signal_data_) {
820                 assert(d);
821                 const vector< shared_ptr<pv::data::Segment> > segments =
822                         d->segments();
823                 for (const shared_ptr<pv::data::Segment>& s : segments)
824                         samplerate = max(samplerate, s->samplerate());
825         }
826         // If there is no sample rate given we use samples as unit
827         if (samplerate == 0.0)
828                 samplerate = 1.0;
829
830         return samplerate;
831 }
832
833 uint32_t Session::get_segment_count() const
834 {
835         uint32_t value = 0;
836
837         // Find the highest number of segments
838         for (const shared_ptr<data::SignalData>& data : all_signal_data_)
839                 if (data->get_segment_count() > value)
840                         value = data->get_segment_count();
841
842         return value;
843 }
844
845 vector<util::Timestamp> Session::get_triggers(uint32_t segment_id) const
846 {
847         vector<util::Timestamp> result;
848
849         for (const pair<uint32_t, util::Timestamp>& entry : trigger_list_)
850                 if (entry.first == segment_id)
851                         result.push_back(entry.second);
852
853         return result;
854 }
855
856 const vector< shared_ptr<data::SignalBase> > Session::signalbases() const
857 {
858         return signalbases_;
859 }
860
861 bool Session::all_segments_complete(uint32_t segment_id) const
862 {
863         bool all_complete = true;
864
865         for (const shared_ptr<data::SignalBase>& base : signalbases_)
866                 if (!base->segment_is_complete(segment_id))
867                         all_complete = false;
868
869         return all_complete;
870 }
871
872 #ifdef ENABLE_DECODE
873 shared_ptr<data::DecodeSignal> Session::add_decode_signal()
874 {
875         shared_ptr<data::DecodeSignal> signal;
876
877         try {
878                 // Create the decode signal
879                 signal = make_shared<data::DecodeSignal>(*this);
880
881                 signalbases_.push_back(signal);
882
883                 // Add the decode signal to all views
884                 for (shared_ptr<views::ViewBase>& view : views_)
885                         view->add_decode_signal(signal);
886         } catch (runtime_error& e) {
887                 remove_decode_signal(signal);
888                 return nullptr;
889         }
890
891         signals_changed();
892
893         return signal;
894 }
895
896 void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
897 {
898         signalbases_.erase(std::remove_if(signalbases_.begin(), signalbases_.end(),
899                 [&](shared_ptr<data::SignalBase> s) { return s == signal; }),
900                 signalbases_.end());
901
902         for (shared_ptr<views::ViewBase>& view : views_)
903                 view->remove_decode_signal(signal);
904
905         signals_changed();
906 }
907 #endif
908
909 void Session::set_capture_state(capture_state state)
910 {
911         bool changed;
912
913         if (state == Running)
914                 acq_time_.restart();
915         if (state == Stopped)
916                 qDebug("Acquisition took %.2f s", acq_time_.elapsed() / 1000.);
917
918         {
919                 lock_guard<mutex> lock(sampling_mutex_);
920                 changed = capture_state_ != state;
921                 capture_state_ = state;
922         }
923
924         if (changed)
925                 capture_state_changed(state);
926 }
927
928 void Session::update_signals()
929 {
930         if (!device_) {
931                 signalbases_.clear();
932                 logic_data_.reset();
933                 for (shared_ptr<views::ViewBase>& view : views_) {
934                         view->clear_signals();
935 #ifdef ENABLE_DECODE
936                         view->clear_decode_signals();
937 #endif
938                 }
939                 return;
940         }
941
942         lock_guard<recursive_mutex> lock(data_mutex_);
943
944         const shared_ptr<sigrok::Device> sr_dev = device_->device();
945         if (!sr_dev) {
946                 signalbases_.clear();
947                 logic_data_.reset();
948                 for (shared_ptr<views::ViewBase>& view : views_) {
949                         view->clear_signals();
950 #ifdef ENABLE_DECODE
951                         view->clear_decode_signals();
952 #endif
953                 }
954                 return;
955         }
956
957         // Detect what data types we will receive
958         auto channels = sr_dev->channels();
959         unsigned int logic_channel_count = count_if(
960                 channels.begin(), channels.end(),
961                 [] (shared_ptr<Channel> channel) {
962                         return channel->type() == sigrok::ChannelType::LOGIC; });
963
964         // Create data containers for the logic data segments
965         {
966                 lock_guard<recursive_mutex> data_lock(data_mutex_);
967
968                 if (logic_channel_count == 0) {
969                         logic_data_.reset();
970                 } else if (!logic_data_ ||
971                         logic_data_->num_channels() != logic_channel_count) {
972                         logic_data_.reset(new data::Logic(
973                                 logic_channel_count));
974                         assert(logic_data_);
975                 }
976         }
977
978         // Make the signals list
979         for (shared_ptr<views::ViewBase>& viewbase : views_) {
980                 views::trace::View *trace_view =
981                         qobject_cast<views::trace::View*>(viewbase.get());
982
983                 if (trace_view) {
984                         unordered_set< shared_ptr<Signal> > prev_sigs(trace_view->signals());
985                         trace_view->clear_signals();
986
987                         for (auto channel : sr_dev->channels()) {
988                                 shared_ptr<data::SignalBase> signalbase;
989                                 shared_ptr<Signal> signal;
990
991                                 // Find the channel in the old signals
992                                 const auto iter = find_if(
993                                         prev_sigs.cbegin(), prev_sigs.cend(),
994                                         [&](const shared_ptr<Signal> &s) {
995                                                 return s->base()->channel() == channel;
996                                         });
997                                 if (iter != prev_sigs.end()) {
998                                         // Copy the signal from the old set to the new
999                                         signal = *iter;
1000                                         trace_view->add_signal(signal);
1001                                 } else {
1002                                         // Find the signalbase for this channel if possible
1003                                         signalbase.reset();
1004                                         for (const shared_ptr<data::SignalBase>& b : signalbases_)
1005                                                 if (b->channel() == channel)
1006                                                         signalbase = b;
1007
1008                                         shared_ptr<Signal> signal;
1009
1010                                         switch(channel->type()->id()) {
1011                                         case SR_CHANNEL_LOGIC:
1012                                                 if (!signalbase) {
1013                                                         signalbase = make_shared<data::SignalBase>(channel,
1014                                                                 data::SignalBase::LogicChannel);
1015                                                         signalbases_.push_back(signalbase);
1016
1017                                                         all_signal_data_.insert(logic_data_);
1018                                                         signalbase->set_data(logic_data_);
1019
1020                                                         connect(this, SIGNAL(capture_state_changed(int)),
1021                                                                 signalbase.get(), SLOT(on_capture_state_changed(int)));
1022                                                 }
1023
1024                                                 signal = shared_ptr<Signal>(new LogicSignal(*this, device_, signalbase));
1025                                                 break;
1026
1027                                         case SR_CHANNEL_ANALOG:
1028                                         {
1029                                                 if (!signalbase) {
1030                                                         signalbase = make_shared<data::SignalBase>(channel,
1031                                                                 data::SignalBase::AnalogChannel);
1032                                                         signalbases_.push_back(signalbase);
1033
1034                                                         shared_ptr<data::Analog> data(new data::Analog());
1035                                                         all_signal_data_.insert(data);
1036                                                         signalbase->set_data(data);
1037
1038                                                         connect(this, SIGNAL(capture_state_changed(int)),
1039                                                                 signalbase.get(), SLOT(on_capture_state_changed(int)));
1040                                                 }
1041
1042                                                 signal = shared_ptr<Signal>(new AnalogSignal(*this, signalbase));
1043                                                 break;
1044                                         }
1045
1046                                         default:
1047                                                 assert(false);
1048                                                 break;
1049                                         }
1050
1051                                         // New views take their signal settings from the main view
1052                                         if (!viewbase->is_main_view()) {
1053                                                 shared_ptr<pv::views::trace::View> main_tv =
1054                                                         dynamic_pointer_cast<pv::views::trace::View>(main_view_);
1055                                                 shared_ptr<Signal> main_signal =
1056                                                         main_tv->get_signal_by_signalbase(signalbase);
1057                                                 signal->restore_settings(main_signal->save_settings());
1058                                         }
1059
1060                                         trace_view->add_signal(signal);
1061                                 }
1062                         }
1063                 }
1064         }
1065
1066         signals_changed();
1067 }
1068
1069 shared_ptr<data::SignalBase> Session::signalbase_from_channel(
1070         shared_ptr<sigrok::Channel> channel) const
1071 {
1072         for (shared_ptr<data::SignalBase> sig : signalbases_) {
1073                 assert(sig);
1074                 if (sig->channel() == channel)
1075                         return sig;
1076         }
1077         return shared_ptr<data::SignalBase>();
1078 }
1079
1080 void Session::sample_thread_proc(function<void (const QString)> error_handler)
1081 {
1082         assert(error_handler);
1083
1084 #ifdef ENABLE_FLOW
1085         pipeline_ = Pipeline::create();
1086
1087         source_ = ElementFactory::create_element("filesrc", "source");
1088         sink_ = RefPtr<AppSink>::cast_dynamic(ElementFactory::create_element("appsink", "sink"));
1089
1090         pipeline_->add(source_)->add(sink_);
1091         source_->link(sink_);
1092
1093         source_->set_property("location", Glib::ustring("/tmp/dummy_binary"));
1094
1095         sink_->set_property("emit-signals", TRUE);
1096         sink_->signal_new_sample().connect(sigc::mem_fun(*this, &Session::on_gst_new_sample));
1097
1098         // Get the bus from the pipeline and add a bus watch to the default main context
1099         RefPtr<Bus> bus = pipeline_->get_bus();
1100         bus->add_watch(sigc::mem_fun(this, &Session::on_gst_bus_message));
1101
1102         // Start pipeline and Wait until it finished processing
1103         pipeline_done_interrupt_ = false;
1104         pipeline_->set_state(Gst::STATE_PLAYING);
1105
1106         unique_lock<mutex> pipeline_done_lock_(pipeline_done_mutex_);
1107         pipeline_done_cond_.wait(pipeline_done_lock_);
1108
1109         // Let the pipeline free all resources
1110         pipeline_->set_state(Gst::STATE_NULL);
1111
1112 #else
1113         if (!device_)
1114                 return;
1115
1116         try {
1117                 cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1118         } catch (Error& e) {
1119                 cur_samplerate_ = 0;
1120         }
1121
1122         out_of_memory_ = false;
1123
1124         {
1125                 lock_guard<recursive_mutex> lock(data_mutex_);
1126                 cur_logic_segment_.reset();
1127                 cur_analog_segments_.clear();
1128         }
1129         highest_segment_id_ = -1;
1130         frame_began_ = false;
1131
1132         try {
1133                 device_->start();
1134         } catch (Error& e) {
1135                 error_handler(e.what());
1136                 return;
1137         }
1138
1139         set_capture_state(device_->session()->trigger() ?
1140                 AwaitingTrigger : Running);
1141
1142         try {
1143                 device_->run();
1144         } catch (Error& e) {
1145                 error_handler(e.what());
1146                 set_capture_state(Stopped);
1147                 return;
1148         } catch (QString& e) {
1149                 error_handler(e);
1150                 set_capture_state(Stopped);
1151                 return;
1152         }
1153
1154         set_capture_state(Stopped);
1155
1156         // Confirm that SR_DF_END was received
1157         if (cur_logic_segment_)
1158                 qDebug() << "WARNING: SR_DF_END was not received.";
1159 #endif
1160
1161         // Optimize memory usage
1162         free_unused_memory();
1163
1164         // We now have unsaved data unless we just "captured" from a file
1165         shared_ptr<devices::File> file_device =
1166                 dynamic_pointer_cast<devices::File>(device_);
1167
1168         if (!file_device)
1169                 data_saved_ = false;
1170
1171         if (out_of_memory_)
1172                 error_handler(tr("Out of memory, acquisition stopped."));
1173 }
1174
1175 void Session::free_unused_memory()
1176 {
1177         for (const shared_ptr<data::SignalData>& data : all_signal_data_) {
1178                 const vector< shared_ptr<data::Segment> > segments = data->segments();
1179
1180                 for (const shared_ptr<data::Segment>& segment : segments)
1181                         segment->free_unused_memory();
1182         }
1183 }
1184
1185 void Session::signal_new_segment()
1186 {
1187         int new_segment_id = 0;
1188
1189         if ((cur_logic_segment_ != nullptr) || !cur_analog_segments_.empty()) {
1190
1191                 // Determine new frame/segment number, assuming that all
1192                 // signals have the same number of frames/segments
1193                 if (cur_logic_segment_) {
1194                         new_segment_id = logic_data_->get_segment_count() - 1;
1195                 } else {
1196                         shared_ptr<sigrok::Channel> any_channel =
1197                                 (*cur_analog_segments_.begin()).first;
1198
1199                         shared_ptr<data::SignalBase> base = signalbase_from_channel(any_channel);
1200                         assert(base);
1201
1202                         shared_ptr<data::Analog> data(base->analog_data());
1203                         assert(data);
1204
1205                         new_segment_id = data->get_segment_count() - 1;
1206                 }
1207         }
1208
1209         if (new_segment_id > highest_segment_id_) {
1210                 highest_segment_id_ = new_segment_id;
1211                 new_segment(highest_segment_id_);
1212         }
1213 }
1214
1215 void Session::signal_segment_completed()
1216 {
1217         int segment_id = 0;
1218
1219         for (const shared_ptr<data::SignalBase>& signalbase : signalbases_) {
1220                 // We only care about analog and logic channels, not derived ones
1221                 if (signalbase->type() == data::SignalBase::AnalogChannel) {
1222                         segment_id = signalbase->analog_data()->get_segment_count() - 1;
1223                         break;
1224                 }
1225
1226                 if (signalbase->type() == data::SignalBase::LogicChannel) {
1227                         segment_id = signalbase->logic_data()->get_segment_count() - 1;
1228                         break;
1229                 }
1230         }
1231
1232         if (segment_id >= 0)
1233                 segment_completed(segment_id);
1234 }
1235
1236 #ifdef ENABLE_FLOW
1237 bool Session::on_gst_bus_message(const Glib::RefPtr<Gst::Bus>& bus, const Glib::RefPtr<Gst::Message>& message)
1238 {
1239         (void)bus;
1240
1241         if ((message->get_source() == pipeline_) && \
1242                 ((message->get_message_type() == Gst::MESSAGE_EOS)))
1243                 pipeline_done_cond_.notify_one();
1244
1245         // TODO Also evaluate MESSAGE_STREAM_STATUS to receive error notifications
1246
1247         return true;
1248 }
1249
1250 Gst::FlowReturn Session::on_gst_new_sample()
1251 {
1252         RefPtr<Gst::Sample> sample = sink_->pull_sample();
1253         RefPtr<Gst::Buffer> buf = sample->get_buffer();
1254
1255         for (uint32_t block_id = 0; block_id < buf->n_memory(); block_id++) {
1256                 RefPtr<Gst::Memory> buf_mem = buf->get_memory(block_id);
1257                 Gst::MapInfo mapinfo;
1258                 buf_mem->map(mapinfo, Gst::MAP_READ);
1259
1260                 shared_ptr<sigrok::Packet> logic_packet =
1261                         sr_context->create_logic_packet(mapinfo.get_data(), buf->get_size(), 1);
1262
1263                 try {
1264                         feed_in_logic(dynamic_pointer_cast<sigrok::Logic>(logic_packet->payload()));
1265                 } catch (bad_alloc&) {
1266                         out_of_memory_ = true;
1267                         device_->stop();
1268                         buf_mem->unmap(mapinfo);
1269                         return Gst::FLOW_ERROR;
1270                 }
1271
1272                 buf_mem->unmap(mapinfo);
1273         }
1274
1275         return Gst::FLOW_OK;
1276 }
1277 #endif
1278
1279 void Session::feed_in_header()
1280 {
1281         // Nothing to do here for now
1282 }
1283
1284 void Session::feed_in_meta(shared_ptr<Meta> meta)
1285 {
1286         for (auto& entry : meta->config()) {
1287                 switch (entry.first->id()) {
1288                 case SR_CONF_SAMPLERATE:
1289                         cur_samplerate_ = g_variant_get_uint64(entry.second.gobj());
1290                         break;
1291                 default:
1292                         qDebug() << "Received meta data key" << entry.first->id() << ", ignoring.";
1293                         break;
1294                 }
1295         }
1296
1297         signals_changed();
1298 }
1299
1300 void Session::feed_in_trigger()
1301 {
1302         // The channel containing most samples should be most accurate
1303         uint64_t sample_count = 0;
1304
1305         {
1306                 for (const shared_ptr<pv::data::SignalData>& d : all_signal_data_) {
1307                         assert(d);
1308                         uint64_t temp_count = 0;
1309
1310                         const vector< shared_ptr<pv::data::Segment> > segments =
1311                                 d->segments();
1312                         for (const shared_ptr<pv::data::Segment> &s : segments)
1313                                 temp_count += s->get_sample_count();
1314
1315                         if (temp_count > sample_count)
1316                                 sample_count = temp_count;
1317                 }
1318         }
1319
1320         uint32_t segment_id = 0;  // Default segment when no frames are used
1321
1322         // If a frame began, we'd ideally be able to use the highest segment ID for
1323         // the trigger. However, as new segments are only created when logic or
1324         // analog data comes in, this doesn't work if the trigger appears right
1325         // after the beginning of the frame, before any sample data.
1326         // For this reason, we use highest segment ID + 1 if no sample data came in
1327         // yet and the highest segment ID otherwise.
1328         if (frame_began_) {
1329                 segment_id = highest_segment_id_;
1330                 if (!cur_logic_segment_ && (cur_analog_segments_.size() == 0))
1331                         segment_id++;
1332         }
1333
1334         // TODO Create timestamp from segment start time + segment's current sample count
1335         util::Timestamp timestamp = sample_count / get_samplerate();
1336         trigger_list_.emplace_back(segment_id, timestamp);
1337         trigger_event(segment_id, timestamp);
1338 }
1339
1340 void Session::feed_in_frame_begin()
1341 {
1342         frame_began_ = true;
1343 }
1344
1345 void Session::feed_in_frame_end()
1346 {
1347         if (!frame_began_)
1348                 return;
1349
1350         {
1351                 lock_guard<recursive_mutex> lock(data_mutex_);
1352
1353                 if (cur_logic_segment_)
1354                         cur_logic_segment_->set_complete();
1355
1356                 for (auto& entry : cur_analog_segments_) {
1357                         shared_ptr<data::AnalogSegment> segment = entry.second;
1358                         segment->set_complete();
1359                 }
1360
1361                 cur_logic_segment_.reset();
1362                 cur_analog_segments_.clear();
1363         }
1364
1365         frame_began_ = false;
1366
1367         signal_segment_completed();
1368 }
1369
1370 void Session::feed_in_logic(shared_ptr<Logic> logic)
1371 {
1372         if (logic->data_length() == 0) {
1373                 qDebug() << "WARNING: Received logic packet with 0 samples.";
1374                 return;
1375         }
1376
1377         if (logic->unit_size() > 8)
1378                 throw QString(tr("Can't handle more than 64 logic channels."));
1379
1380         if (!cur_samplerate_)
1381                 try {
1382                         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1383                 } catch (Error& e) {
1384                         // Do nothing
1385                 }
1386
1387         lock_guard<recursive_mutex> lock(data_mutex_);
1388
1389         if (!logic_data_) {
1390                 // The only reason logic_data_ would not have been created is
1391                 // if it was not possible to determine the signals when the
1392                 // device was created.
1393                 update_signals();
1394         }
1395
1396         if (!cur_logic_segment_) {
1397                 // This could be the first packet after a trigger
1398                 set_capture_state(Running);
1399
1400                 // Create a new data segment
1401                 cur_logic_segment_ = make_shared<data::LogicSegment>(
1402                         *logic_data_, logic_data_->get_segment_count(),
1403                         logic->unit_size(), cur_samplerate_);
1404                 logic_data_->push_segment(cur_logic_segment_);
1405
1406                 signal_new_segment();
1407         }
1408
1409         cur_logic_segment_->append_payload(logic);
1410
1411         data_received();
1412 }
1413
1414 void Session::feed_in_analog(shared_ptr<Analog> analog)
1415 {
1416         if (analog->num_samples() == 0) {
1417                 qDebug() << "WARNING: Received analog packet with 0 samples.";
1418                 return;
1419         }
1420
1421         if (!cur_samplerate_)
1422                 try {
1423                         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1424                 } catch (Error& e) {
1425                         // Do nothing
1426                 }
1427
1428         lock_guard<recursive_mutex> lock(data_mutex_);
1429
1430         const vector<shared_ptr<Channel>> channels = analog->channels();
1431         bool sweep_beginning = false;
1432
1433         unique_ptr<float[]> data(new float[analog->num_samples() * channels.size()]);
1434         analog->get_data_as_float(data.get());
1435
1436         if (signalbases_.empty())
1437                 update_signals();
1438
1439         float *channel_data = data.get();
1440         for (auto& channel : channels) {
1441                 shared_ptr<data::AnalogSegment> segment;
1442
1443                 // Try to get the segment of the channel
1444                 const map< shared_ptr<Channel>, shared_ptr<data::AnalogSegment> >::
1445                         iterator iter = cur_analog_segments_.find(channel);
1446                 if (iter != cur_analog_segments_.end())
1447                         segment = (*iter).second;
1448                 else {
1449                         // If no segment was found, this means we haven't
1450                         // created one yet. i.e. this is the first packet
1451                         // in the sweep containing this segment.
1452                         sweep_beginning = true;
1453
1454                         // Find the analog data associated with the channel
1455                         shared_ptr<data::SignalBase> base = signalbase_from_channel(channel);
1456                         assert(base);
1457
1458                         shared_ptr<data::Analog> data(base->analog_data());
1459                         assert(data);
1460
1461                         // Create a segment, keep it in the maps of channels
1462                         segment = make_shared<data::AnalogSegment>(
1463                                 *data, data->get_segment_count(), cur_samplerate_);
1464                         cur_analog_segments_[channel] = segment;
1465
1466                         // Push the segment into the analog data.
1467                         data->push_segment(segment);
1468
1469                         signal_new_segment();
1470                 }
1471
1472                 assert(segment);
1473
1474                 // Append the samples in the segment
1475                 segment->append_interleaved_samples(channel_data++, analog->num_samples(),
1476                         channels.size());
1477         }
1478
1479         if (sweep_beginning) {
1480                 // This could be the first packet after a trigger
1481                 set_capture_state(Running);
1482         }
1483
1484         data_received();
1485 }
1486
1487 void Session::data_feed_in(shared_ptr<sigrok::Device> device,
1488         shared_ptr<Packet> packet)
1489 {
1490         (void)device;
1491
1492         assert(device);
1493         assert(device == device_->device());
1494         assert(packet);
1495
1496         switch (packet->type()->id()) {
1497         case SR_DF_HEADER:
1498                 feed_in_header();
1499                 break;
1500
1501         case SR_DF_META:
1502                 feed_in_meta(dynamic_pointer_cast<Meta>(packet->payload()));
1503                 break;
1504
1505         case SR_DF_TRIGGER:
1506                 feed_in_trigger();
1507                 break;
1508
1509         case SR_DF_LOGIC:
1510                 try {
1511                         feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
1512                 } catch (bad_alloc&) {
1513                         out_of_memory_ = true;
1514                         device_->stop();
1515                 }
1516                 break;
1517
1518         case SR_DF_ANALOG:
1519                 try {
1520                         feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
1521                 } catch (bad_alloc&) {
1522                         out_of_memory_ = true;
1523                         device_->stop();
1524                 }
1525                 break;
1526
1527         case SR_DF_FRAME_BEGIN:
1528                 feed_in_frame_begin();
1529                 break;
1530
1531         case SR_DF_FRAME_END:
1532                 feed_in_frame_end();
1533                 break;
1534
1535         case SR_DF_END:
1536                 // Strictly speaking, this is performed when a frame end marker was
1537                 // received, so there's no point doing this again. However, not all
1538                 // devices use frames, and for those devices, we need to do it here.
1539                 {
1540                         lock_guard<recursive_mutex> lock(data_mutex_);
1541
1542                         if (cur_logic_segment_)
1543                                 cur_logic_segment_->set_complete();
1544
1545                         for (auto& entry : cur_analog_segments_) {
1546                                 shared_ptr<data::AnalogSegment> segment = entry.second;
1547                                 segment->set_complete();
1548                         }
1549
1550                         cur_logic_segment_.reset();
1551                         cur_analog_segments_.clear();
1552                 }
1553                 break;
1554
1555         default:
1556                 break;
1557         }
1558 }
1559
1560 void Session::on_data_saved()
1561 {
1562         data_saved_ = true;
1563 }
1564
1565 #ifdef ENABLE_DECODE
1566 void Session::on_new_decoders_selected(vector<const srd_decoder*> decoders)
1567 {
1568         assert(decoders.size() > 0);
1569
1570         shared_ptr<data::DecodeSignal> signal = add_decode_signal();
1571
1572         if (signal)
1573                 for (unsigned int i = 0; i < decoders.size(); i++) {
1574                         const srd_decoder* d = decoders[i];
1575                         signal->stack_decoder(d, !(i < decoders.size() - 1));
1576                 }
1577 }
1578 #endif
1579
1580 } // namespace pv