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