]> sigrok.org Git - pulseview.git/blob - pv/session.cpp
Session: Save meta objs for all views
[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
795         std::remove_if(views_.begin(), views_.end(), [&](shared_ptr<views::ViewBase> v) { return v == view; });
796
797         if (views_.empty()) {
798                 main_view_.reset();
799
800                 // Without a view there can be no main bar
801                 main_bar_.reset();
802         }
803 }
804
805 bool Session::has_view(shared_ptr<views::ViewBase> view)
806 {
807         for (shared_ptr<views::ViewBase>& v : views_)
808                 if (v == view)
809                         return true;
810
811         return false;
812 }
813
814 double Session::get_samplerate() const
815 {
816         double samplerate = 0.0;
817
818         for (const shared_ptr<pv::data::SignalData>& d : all_signal_data_) {
819                 assert(d);
820                 const vector< shared_ptr<pv::data::Segment> > segments =
821                         d->segments();
822                 for (const shared_ptr<pv::data::Segment>& s : segments)
823                         samplerate = max(samplerate, s->samplerate());
824         }
825         // If there is no sample rate given we use samples as unit
826         if (samplerate == 0.0)
827                 samplerate = 1.0;
828
829         return samplerate;
830 }
831
832 uint32_t Session::get_segment_count() const
833 {
834         uint32_t value = 0;
835
836         // Find the highest number of segments
837         for (const shared_ptr<data::SignalData>& data : all_signal_data_)
838                 if (data->get_segment_count() > value)
839                         value = data->get_segment_count();
840
841         return value;
842 }
843
844 vector<util::Timestamp> Session::get_triggers(uint32_t segment_id) const
845 {
846         vector<util::Timestamp> result;
847
848         for (const pair<uint32_t, util::Timestamp>& entry : trigger_list_)
849                 if (entry.first == segment_id)
850                         result.push_back(entry.second);
851
852         return result;
853 }
854
855 const unordered_set< shared_ptr<data::SignalBase> > Session::signalbases() const
856 {
857         return signalbases_;
858 }
859
860 bool Session::all_segments_complete(uint32_t segment_id) const
861 {
862         bool all_complete = true;
863
864         for (const shared_ptr<data::SignalBase>& base : signalbases_)
865                 if (!base->segment_is_complete(segment_id))
866                         all_complete = false;
867
868         return all_complete;
869 }
870
871 #ifdef ENABLE_DECODE
872 shared_ptr<data::DecodeSignal> Session::add_decode_signal()
873 {
874         shared_ptr<data::DecodeSignal> signal;
875
876         try {
877                 // Create the decode signal
878                 signal = make_shared<data::DecodeSignal>(*this);
879
880                 signalbases_.insert(signal);
881
882                 // Add the decode signal to all views
883                 for (shared_ptr<views::ViewBase>& view : views_)
884                         view->add_decode_signal(signal);
885         } catch (runtime_error& e) {
886                 remove_decode_signal(signal);
887                 return nullptr;
888         }
889
890         signals_changed();
891
892         return signal;
893 }
894
895 void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
896 {
897         signalbases_.erase(signal);
898
899         for (shared_ptr<views::ViewBase>& view : views_)
900                 view->remove_decode_signal(signal);
901
902         signals_changed();
903 }
904 #endif
905
906 void Session::set_capture_state(capture_state state)
907 {
908         bool changed;
909
910         if (state == Running)
911                 acq_time_.restart();
912         if (state == Stopped)
913                 qDebug("Acquisition took %.2f s", acq_time_.elapsed() / 1000.);
914
915         {
916                 lock_guard<mutex> lock(sampling_mutex_);
917                 changed = capture_state_ != state;
918                 capture_state_ = state;
919         }
920
921         if (changed)
922                 capture_state_changed(state);
923 }
924
925 void Session::update_signals()
926 {
927         if (!device_) {
928                 signalbases_.clear();
929                 logic_data_.reset();
930                 for (shared_ptr<views::ViewBase>& view : views_) {
931                         view->clear_signals();
932 #ifdef ENABLE_DECODE
933                         view->clear_decode_signals();
934 #endif
935                 }
936                 return;
937         }
938
939         lock_guard<recursive_mutex> lock(data_mutex_);
940
941         const shared_ptr<sigrok::Device> sr_dev = device_->device();
942         if (!sr_dev) {
943                 signalbases_.clear();
944                 logic_data_.reset();
945                 for (shared_ptr<views::ViewBase>& view : views_) {
946                         view->clear_signals();
947 #ifdef ENABLE_DECODE
948                         view->clear_decode_signals();
949 #endif
950                 }
951                 return;
952         }
953
954         // Detect what data types we will receive
955         auto channels = sr_dev->channels();
956         unsigned int logic_channel_count = count_if(
957                 channels.begin(), channels.end(),
958                 [] (shared_ptr<Channel> channel) {
959                         return channel->type() == sigrok::ChannelType::LOGIC; });
960
961         // Create data containers for the logic data segments
962         {
963                 lock_guard<recursive_mutex> data_lock(data_mutex_);
964
965                 if (logic_channel_count == 0) {
966                         logic_data_.reset();
967                 } else if (!logic_data_ ||
968                         logic_data_->num_channels() != logic_channel_count) {
969                         logic_data_.reset(new data::Logic(
970                                 logic_channel_count));
971                         assert(logic_data_);
972                 }
973         }
974
975         // Make the signals list
976         for (shared_ptr<views::ViewBase>& viewbase : views_) {
977                 views::trace::View *trace_view =
978                         qobject_cast<views::trace::View*>(viewbase.get());
979
980                 if (trace_view) {
981                         unordered_set< shared_ptr<Signal> > prev_sigs(trace_view->signals());
982                         trace_view->clear_signals();
983
984                         for (auto channel : sr_dev->channels()) {
985                                 shared_ptr<data::SignalBase> signalbase;
986                                 shared_ptr<Signal> signal;
987
988                                 // Find the channel in the old signals
989                                 const auto iter = find_if(
990                                         prev_sigs.cbegin(), prev_sigs.cend(),
991                                         [&](const shared_ptr<Signal> &s) {
992                                                 return s->base()->channel() == channel;
993                                         });
994                                 if (iter != prev_sigs.end()) {
995                                         // Copy the signal from the old set to the new
996                                         signal = *iter;
997                                         trace_view->add_signal(signal);
998                                 } else {
999                                         // Find the signalbase for this channel if possible
1000                                         signalbase.reset();
1001                                         for (const shared_ptr<data::SignalBase>& b : signalbases_)
1002                                                 if (b->channel() == channel)
1003                                                         signalbase = b;
1004
1005                                         shared_ptr<Signal> signal;
1006
1007                                         switch(channel->type()->id()) {
1008                                         case SR_CHANNEL_LOGIC:
1009                                                 if (!signalbase) {
1010                                                         signalbase = make_shared<data::SignalBase>(channel,
1011                                                                 data::SignalBase::LogicChannel);
1012                                                         signalbases_.insert(signalbase);
1013
1014                                                         all_signal_data_.insert(logic_data_);
1015                                                         signalbase->set_data(logic_data_);
1016
1017                                                         connect(this, SIGNAL(capture_state_changed(int)),
1018                                                                 signalbase.get(), SLOT(on_capture_state_changed(int)));
1019                                                 }
1020
1021                                                 signal = shared_ptr<Signal>(new LogicSignal(*this, device_, signalbase));
1022                                                 break;
1023
1024                                         case SR_CHANNEL_ANALOG:
1025                                         {
1026                                                 if (!signalbase) {
1027                                                         signalbase = make_shared<data::SignalBase>(channel,
1028                                                                 data::SignalBase::AnalogChannel);
1029                                                         signalbases_.insert(signalbase);
1030
1031                                                         shared_ptr<data::Analog> data(new data::Analog());
1032                                                         all_signal_data_.insert(data);
1033                                                         signalbase->set_data(data);
1034
1035                                                         connect(this, SIGNAL(capture_state_changed(int)),
1036                                                                 signalbase.get(), SLOT(on_capture_state_changed(int)));
1037                                                 }
1038
1039                                                 signal = shared_ptr<Signal>(new AnalogSignal(*this, signalbase));
1040                                                 break;
1041                                         }
1042
1043                                         default:
1044                                                 assert(false);
1045                                                 break;
1046                                         }
1047
1048                                         // New views take their signal settings from the main view
1049                                         if (!viewbase->is_main_view()) {
1050                                                 shared_ptr<pv::views::trace::View> main_tv =
1051                                                         dynamic_pointer_cast<pv::views::trace::View>(main_view_);
1052                                                 shared_ptr<Signal> main_signal =
1053                                                         main_tv->get_signal_by_signalbase(signalbase);
1054                                                 signal->restore_settings(main_signal->save_settings());
1055                                         }
1056
1057                                         trace_view->add_signal(signal);
1058                                 }
1059                         }
1060                 }
1061         }
1062
1063         signals_changed();
1064 }
1065
1066 shared_ptr<data::SignalBase> Session::signalbase_from_channel(
1067         shared_ptr<sigrok::Channel> channel) const
1068 {
1069         for (shared_ptr<data::SignalBase> sig : signalbases_) {
1070                 assert(sig);
1071                 if (sig->channel() == channel)
1072                         return sig;
1073         }
1074         return shared_ptr<data::SignalBase>();
1075 }
1076
1077 void Session::sample_thread_proc(function<void (const QString)> error_handler)
1078 {
1079         assert(error_handler);
1080
1081 #ifdef ENABLE_FLOW
1082         pipeline_ = Pipeline::create();
1083
1084         source_ = ElementFactory::create_element("filesrc", "source");
1085         sink_ = RefPtr<AppSink>::cast_dynamic(ElementFactory::create_element("appsink", "sink"));
1086
1087         pipeline_->add(source_)->add(sink_);
1088         source_->link(sink_);
1089
1090         source_->set_property("location", Glib::ustring("/tmp/dummy_binary"));
1091
1092         sink_->set_property("emit-signals", TRUE);
1093         sink_->signal_new_sample().connect(sigc::mem_fun(*this, &Session::on_gst_new_sample));
1094
1095         // Get the bus from the pipeline and add a bus watch to the default main context
1096         RefPtr<Bus> bus = pipeline_->get_bus();
1097         bus->add_watch(sigc::mem_fun(this, &Session::on_gst_bus_message));
1098
1099         // Start pipeline and Wait until it finished processing
1100         pipeline_done_interrupt_ = false;
1101         pipeline_->set_state(Gst::STATE_PLAYING);
1102
1103         unique_lock<mutex> pipeline_done_lock_(pipeline_done_mutex_);
1104         pipeline_done_cond_.wait(pipeline_done_lock_);
1105
1106         // Let the pipeline free all resources
1107         pipeline_->set_state(Gst::STATE_NULL);
1108
1109 #else
1110         if (!device_)
1111                 return;
1112
1113         try {
1114                 cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1115         } catch (Error& e) {
1116                 cur_samplerate_ = 0;
1117         }
1118
1119         out_of_memory_ = false;
1120
1121         {
1122                 lock_guard<recursive_mutex> lock(data_mutex_);
1123                 cur_logic_segment_.reset();
1124                 cur_analog_segments_.clear();
1125         }
1126         highest_segment_id_ = -1;
1127         frame_began_ = false;
1128
1129         try {
1130                 device_->start();
1131         } catch (Error& e) {
1132                 error_handler(e.what());
1133                 return;
1134         }
1135
1136         set_capture_state(device_->session()->trigger() ?
1137                 AwaitingTrigger : Running);
1138
1139         try {
1140                 device_->run();
1141         } catch (Error& e) {
1142                 error_handler(e.what());
1143                 set_capture_state(Stopped);
1144                 return;
1145         } catch (QString& e) {
1146                 error_handler(e);
1147                 set_capture_state(Stopped);
1148                 return;
1149         }
1150
1151         set_capture_state(Stopped);
1152
1153         // Confirm that SR_DF_END was received
1154         if (cur_logic_segment_)
1155                 qDebug() << "WARNING: SR_DF_END was not received.";
1156 #endif
1157
1158         // Optimize memory usage
1159         free_unused_memory();
1160
1161         // We now have unsaved data unless we just "captured" from a file
1162         shared_ptr<devices::File> file_device =
1163                 dynamic_pointer_cast<devices::File>(device_);
1164
1165         if (!file_device)
1166                 data_saved_ = false;
1167
1168         if (out_of_memory_)
1169                 error_handler(tr("Out of memory, acquisition stopped."));
1170 }
1171
1172 void Session::free_unused_memory()
1173 {
1174         for (const shared_ptr<data::SignalData>& data : all_signal_data_) {
1175                 const vector< shared_ptr<data::Segment> > segments = data->segments();
1176
1177                 for (const shared_ptr<data::Segment>& segment : segments)
1178                         segment->free_unused_memory();
1179         }
1180 }
1181
1182 void Session::signal_new_segment()
1183 {
1184         int new_segment_id = 0;
1185
1186         if ((cur_logic_segment_ != nullptr) || !cur_analog_segments_.empty()) {
1187
1188                 // Determine new frame/segment number, assuming that all
1189                 // signals have the same number of frames/segments
1190                 if (cur_logic_segment_) {
1191                         new_segment_id = logic_data_->get_segment_count() - 1;
1192                 } else {
1193                         shared_ptr<sigrok::Channel> any_channel =
1194                                 (*cur_analog_segments_.begin()).first;
1195
1196                         shared_ptr<data::SignalBase> base = signalbase_from_channel(any_channel);
1197                         assert(base);
1198
1199                         shared_ptr<data::Analog> data(base->analog_data());
1200                         assert(data);
1201
1202                         new_segment_id = data->get_segment_count() - 1;
1203                 }
1204         }
1205
1206         if (new_segment_id > highest_segment_id_) {
1207                 highest_segment_id_ = new_segment_id;
1208                 new_segment(highest_segment_id_);
1209         }
1210 }
1211
1212 void Session::signal_segment_completed()
1213 {
1214         int segment_id = 0;
1215
1216         for (const shared_ptr<data::SignalBase>& signalbase : signalbases_) {
1217                 // We only care about analog and logic channels, not derived ones
1218                 if (signalbase->type() == data::SignalBase::AnalogChannel) {
1219                         segment_id = signalbase->analog_data()->get_segment_count() - 1;
1220                         break;
1221                 }
1222
1223                 if (signalbase->type() == data::SignalBase::LogicChannel) {
1224                         segment_id = signalbase->logic_data()->get_segment_count() - 1;
1225                         break;
1226                 }
1227         }
1228
1229         if (segment_id >= 0)
1230                 segment_completed(segment_id);
1231 }
1232
1233 #ifdef ENABLE_FLOW
1234 bool Session::on_gst_bus_message(const Glib::RefPtr<Gst::Bus>& bus, const Glib::RefPtr<Gst::Message>& message)
1235 {
1236         (void)bus;
1237
1238         if ((message->get_source() == pipeline_) && \
1239                 ((message->get_message_type() == Gst::MESSAGE_EOS)))
1240                 pipeline_done_cond_.notify_one();
1241
1242         // TODO Also evaluate MESSAGE_STREAM_STATUS to receive error notifications
1243
1244         return true;
1245 }
1246
1247 Gst::FlowReturn Session::on_gst_new_sample()
1248 {
1249         RefPtr<Gst::Sample> sample = sink_->pull_sample();
1250         RefPtr<Gst::Buffer> buf = sample->get_buffer();
1251
1252         for (uint32_t block_id = 0; block_id < buf->n_memory(); block_id++) {
1253                 RefPtr<Gst::Memory> buf_mem = buf->get_memory(block_id);
1254                 Gst::MapInfo mapinfo;
1255                 buf_mem->map(mapinfo, Gst::MAP_READ);
1256
1257                 shared_ptr<sigrok::Packet> logic_packet =
1258                         sr_context->create_logic_packet(mapinfo.get_data(), buf->get_size(), 1);
1259
1260                 try {
1261                         feed_in_logic(dynamic_pointer_cast<sigrok::Logic>(logic_packet->payload()));
1262                 } catch (bad_alloc&) {
1263                         out_of_memory_ = true;
1264                         device_->stop();
1265                         buf_mem->unmap(mapinfo);
1266                         return Gst::FLOW_ERROR;
1267                 }
1268
1269                 buf_mem->unmap(mapinfo);
1270         }
1271
1272         return Gst::FLOW_OK;
1273 }
1274 #endif
1275
1276 void Session::feed_in_header()
1277 {
1278         // Nothing to do here for now
1279 }
1280
1281 void Session::feed_in_meta(shared_ptr<Meta> meta)
1282 {
1283         for (auto& entry : meta->config()) {
1284                 switch (entry.first->id()) {
1285                 case SR_CONF_SAMPLERATE:
1286                         cur_samplerate_ = g_variant_get_uint64(entry.second.gobj());
1287                         break;
1288                 default:
1289                         qDebug() << "Received meta data key" << entry.first->id() << ", ignoring.";
1290                         break;
1291                 }
1292         }
1293
1294         signals_changed();
1295 }
1296
1297 void Session::feed_in_trigger()
1298 {
1299         // The channel containing most samples should be most accurate
1300         uint64_t sample_count = 0;
1301
1302         {
1303                 for (const shared_ptr<pv::data::SignalData>& d : all_signal_data_) {
1304                         assert(d);
1305                         uint64_t temp_count = 0;
1306
1307                         const vector< shared_ptr<pv::data::Segment> > segments =
1308                                 d->segments();
1309                         for (const shared_ptr<pv::data::Segment> &s : segments)
1310                                 temp_count += s->get_sample_count();
1311
1312                         if (temp_count > sample_count)
1313                                 sample_count = temp_count;
1314                 }
1315         }
1316
1317         uint32_t segment_id = 0;  // Default segment when no frames are used
1318
1319         // If a frame began, we'd ideally be able to use the highest segment ID for
1320         // the trigger. However, as new segments are only created when logic or
1321         // analog data comes in, this doesn't work if the trigger appears right
1322         // after the beginning of the frame, before any sample data.
1323         // For this reason, we use highest segment ID + 1 if no sample data came in
1324         // yet and the highest segment ID otherwise.
1325         if (frame_began_) {
1326                 segment_id = highest_segment_id_;
1327                 if (!cur_logic_segment_ && (cur_analog_segments_.size() == 0))
1328                         segment_id++;
1329         }
1330
1331         // TODO Create timestamp from segment start time + segment's current sample count
1332         util::Timestamp timestamp = sample_count / get_samplerate();
1333         trigger_list_.emplace_back(segment_id, timestamp);
1334         trigger_event(segment_id, timestamp);
1335 }
1336
1337 void Session::feed_in_frame_begin()
1338 {
1339         frame_began_ = true;
1340 }
1341
1342 void Session::feed_in_frame_end()
1343 {
1344         if (!frame_began_)
1345                 return;
1346
1347         {
1348                 lock_guard<recursive_mutex> lock(data_mutex_);
1349
1350                 if (cur_logic_segment_)
1351                         cur_logic_segment_->set_complete();
1352
1353                 for (auto& entry : cur_analog_segments_) {
1354                         shared_ptr<data::AnalogSegment> segment = entry.second;
1355                         segment->set_complete();
1356                 }
1357
1358                 cur_logic_segment_.reset();
1359                 cur_analog_segments_.clear();
1360         }
1361
1362         frame_began_ = false;
1363
1364         signal_segment_completed();
1365 }
1366
1367 void Session::feed_in_logic(shared_ptr<Logic> logic)
1368 {
1369         if (logic->data_length() == 0) {
1370                 qDebug() << "WARNING: Received logic packet with 0 samples.";
1371                 return;
1372         }
1373
1374         if (logic->unit_size() > 8)
1375                 throw QString(tr("Can't handle more than 64 logic channels."));
1376
1377         if (!cur_samplerate_)
1378                 try {
1379                         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1380                 } catch (Error& e) {
1381                         // Do nothing
1382                 }
1383
1384         lock_guard<recursive_mutex> lock(data_mutex_);
1385
1386         if (!logic_data_) {
1387                 // The only reason logic_data_ would not have been created is
1388                 // if it was not possible to determine the signals when the
1389                 // device was created.
1390                 update_signals();
1391         }
1392
1393         if (!cur_logic_segment_) {
1394                 // This could be the first packet after a trigger
1395                 set_capture_state(Running);
1396
1397                 // Create a new data segment
1398                 cur_logic_segment_ = make_shared<data::LogicSegment>(
1399                         *logic_data_, logic_data_->get_segment_count(),
1400                         logic->unit_size(), cur_samplerate_);
1401                 logic_data_->push_segment(cur_logic_segment_);
1402
1403                 signal_new_segment();
1404         }
1405
1406         cur_logic_segment_->append_payload(logic);
1407
1408         data_received();
1409 }
1410
1411 void Session::feed_in_analog(shared_ptr<Analog> analog)
1412 {
1413         if (analog->num_samples() == 0) {
1414                 qDebug() << "WARNING: Received analog packet with 0 samples.";
1415                 return;
1416         }
1417
1418         if (!cur_samplerate_)
1419                 try {
1420                         cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
1421                 } catch (Error& e) {
1422                         // Do nothing
1423                 }
1424
1425         lock_guard<recursive_mutex> lock(data_mutex_);
1426
1427         const vector<shared_ptr<Channel>> channels = analog->channels();
1428         bool sweep_beginning = false;
1429
1430         unique_ptr<float[]> data(new float[analog->num_samples() * channels.size()]);
1431         analog->get_data_as_float(data.get());
1432
1433         if (signalbases_.empty())
1434                 update_signals();
1435
1436         float *channel_data = data.get();
1437         for (auto& channel : channels) {
1438                 shared_ptr<data::AnalogSegment> segment;
1439
1440                 // Try to get the segment of the channel
1441                 const map< shared_ptr<Channel>, shared_ptr<data::AnalogSegment> >::
1442                         iterator iter = cur_analog_segments_.find(channel);
1443                 if (iter != cur_analog_segments_.end())
1444                         segment = (*iter).second;
1445                 else {
1446                         // If no segment was found, this means we haven't
1447                         // created one yet. i.e. this is the first packet
1448                         // in the sweep containing this segment.
1449                         sweep_beginning = true;
1450
1451                         // Find the analog data associated with the channel
1452                         shared_ptr<data::SignalBase> base = signalbase_from_channel(channel);
1453                         assert(base);
1454
1455                         shared_ptr<data::Analog> data(base->analog_data());
1456                         assert(data);
1457
1458                         // Create a segment, keep it in the maps of channels
1459                         segment = make_shared<data::AnalogSegment>(
1460                                 *data, data->get_segment_count(), cur_samplerate_);
1461                         cur_analog_segments_[channel] = segment;
1462
1463                         // Push the segment into the analog data.
1464                         data->push_segment(segment);
1465
1466                         signal_new_segment();
1467                 }
1468
1469                 assert(segment);
1470
1471                 // Append the samples in the segment
1472                 segment->append_interleaved_samples(channel_data++, analog->num_samples(),
1473                         channels.size());
1474         }
1475
1476         if (sweep_beginning) {
1477                 // This could be the first packet after a trigger
1478                 set_capture_state(Running);
1479         }
1480
1481         data_received();
1482 }
1483
1484 void Session::data_feed_in(shared_ptr<sigrok::Device> device,
1485         shared_ptr<Packet> packet)
1486 {
1487         (void)device;
1488
1489         assert(device);
1490         assert(device == device_->device());
1491         assert(packet);
1492
1493         switch (packet->type()->id()) {
1494         case SR_DF_HEADER:
1495                 feed_in_header();
1496                 break;
1497
1498         case SR_DF_META:
1499                 feed_in_meta(dynamic_pointer_cast<Meta>(packet->payload()));
1500                 break;
1501
1502         case SR_DF_TRIGGER:
1503                 feed_in_trigger();
1504                 break;
1505
1506         case SR_DF_LOGIC:
1507                 try {
1508                         feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
1509                 } catch (bad_alloc&) {
1510                         out_of_memory_ = true;
1511                         device_->stop();
1512                 }
1513                 break;
1514
1515         case SR_DF_ANALOG:
1516                 try {
1517                         feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
1518                 } catch (bad_alloc&) {
1519                         out_of_memory_ = true;
1520                         device_->stop();
1521                 }
1522                 break;
1523
1524         case SR_DF_FRAME_BEGIN:
1525                 feed_in_frame_begin();
1526                 break;
1527
1528         case SR_DF_FRAME_END:
1529                 feed_in_frame_end();
1530                 break;
1531
1532         case SR_DF_END:
1533                 // Strictly speaking, this is performed when a frame end marker was
1534                 // received, so there's no point doing this again. However, not all
1535                 // devices use frames, and for those devices, we need to do it here.
1536                 {
1537                         lock_guard<recursive_mutex> lock(data_mutex_);
1538
1539                         if (cur_logic_segment_)
1540                                 cur_logic_segment_->set_complete();
1541
1542                         for (auto& entry : cur_analog_segments_) {
1543                                 shared_ptr<data::AnalogSegment> segment = entry.second;
1544                                 segment->set_complete();
1545                         }
1546
1547                         cur_logic_segment_.reset();
1548                         cur_analog_segments_.clear();
1549                 }
1550                 break;
1551
1552         default:
1553                 break;
1554         }
1555 }
1556
1557 void Session::on_data_saved()
1558 {
1559         data_saved_ = true;
1560 }
1561
1562 #ifdef ENABLE_DECODE
1563 void Session::on_new_decoders_selected(vector<const srd_decoder*> decoders)
1564 {
1565         assert(decoders.size() > 0);
1566
1567         shared_ptr<data::DecodeSignal> signal = add_decode_signal();
1568
1569         if (signal)
1570                 for (unsigned int i = 0; i < decoders.size(); i++) {
1571                         const srd_decoder* d = decoders[i];
1572                         signal->stack_decoder(d, !(i < decoders.size() - 1));
1573                 }
1574 }
1575 #endif
1576
1577 } // namespace pv