2 * This file is part of the PulseView project.
4 * Copyright (C) 2012-14 Joel Holdsworth <joel@airwebreathe.org.uk>
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.
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.
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/>.
31 #include "devicemanager.hpp"
32 #include "mainwindow.hpp"
33 #include "session.hpp"
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"
44 #include "devices/hardwaredevice.hpp"
45 #include "devices/inputfile.hpp"
46 #include "devices/sessionfile.hpp"
48 #include "toolbars/mainbar.hpp"
50 #include "views/trace/analogsignal.hpp"
51 #include "views/trace/decodetrace.hpp"
52 #include "views/trace/logicsignal.hpp"
53 #include "views/trace/signal.hpp"
54 #include "views/trace/view.hpp"
56 #include <libsigrokcxx/libsigrokcxx.hpp>
59 #include <gstreamermm.h>
60 #include <libsigrokflow/libsigrokflow.hpp>
64 #include <libsigrokdecode/libsigrokdecode.h>
65 #include "data/decodesignal.hpp"
69 using std::dynamic_pointer_cast
;
73 using std::lock_guard
;
75 using std::make_shared
;
81 using std::recursive_mutex
;
82 using std::runtime_error
;
83 using std::shared_ptr
;
86 using std::unique_lock
;
88 using std::unique_ptr
;
92 using sigrok::Channel
;
93 using sigrok::ConfigKey
;
94 using sigrok::DatafeedCallbackFunction
;
96 using sigrok::InputFormat
;
100 using sigrok::Session
;
102 using Glib::VariantBase
;
106 using Gst::ElementFactory
;
110 using pv::data::SignalGroup
;
111 using pv::util::Timestamp
;
112 using pv::views::trace::Signal
;
113 using pv::views::trace::AnalogSignal
;
114 using pv::views::trace::LogicSignal
;
118 shared_ptr
<sigrok::Context
> Session::sr_context
;
120 Session::Session(DeviceManager
&device_manager
, QString name
) :
121 shutting_down_(false),
122 device_manager_(device_manager
),
125 capture_state_(Stopped
),
129 // Use this name also for the QObject instance
130 setObjectName(name_
);
135 shutting_down_
= true;
137 // Stop and join to the thread
140 for (SignalGroup
* group
: signal_groups_
) {
146 DeviceManager
& Session::device_manager()
148 return device_manager_
;
151 const DeviceManager
& Session::device_manager() const
153 return device_manager_
;
156 shared_ptr
<sigrok::Session
> Session::session() const
159 return shared_ptr
<sigrok::Session
>();
160 return device_
->session();
163 shared_ptr
<devices::Device
> Session::device() const
168 QString
Session::name() const
173 void Session::set_name(QString name
)
175 if (default_name_
.isEmpty())
176 default_name_
= name
;
180 // Use this name also for the QObject instance
181 setObjectName(name_
);
186 QString
Session::save_path() const
191 void Session::set_save_path(QString path
)
196 const vector
< shared_ptr
<views::ViewBase
> > Session::views() const
201 shared_ptr
<views::ViewBase
> Session::main_view() const
206 void Session::set_main_bar(shared_ptr
<pv::toolbars::MainBar
> main_bar
)
208 main_bar_
= main_bar
;
211 shared_ptr
<pv::toolbars::MainBar
> Session::main_bar() const
216 bool Session::data_saved() const
221 void Session::save_setup(QSettings
&settings
) const
224 int decode_signal_count
= 0;
225 int gen_signal_count
= 0;
227 // Save channels and decoders
228 for (const shared_ptr
<data::SignalBase
>& base
: signalbases_
) {
230 if (base
->is_decode_signal()) {
231 settings
.beginGroup("decode_signal" + QString::number(decode_signal_count
++));
232 base
->save_settings(settings
);
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
);
242 settings
.beginGroup(base
->internal_name());
243 base
->save_settings(settings
);
248 settings
.setValue("decode_signals", decode_signal_count
);
249 settings
.setValue("generated_signals", gen_signal_count
);
251 // Save view states and their signal settings
252 // Note: main_view must be saved as view0
254 settings
.beginGroup("view" + QString::number(i
++));
255 main_view_
->save_settings(settings
);
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
);
267 settings
.setValue("views", i
);
271 for (const shared_ptr
<views::ViewBase
>& vb
: views_
) {
272 shared_ptr
<views::trace::View
> tv
= dynamic_pointer_cast
<views::trace::View
>(vb
);
274 for (const shared_ptr
<views::trace::TimeItem
>& time_item
: tv
->time_items()) {
276 const shared_ptr
<views::trace::Flag
> flag
=
277 dynamic_pointer_cast
<views::trace::Flag
>(time_item
);
279 if (!flag
->enabled())
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());
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());
305 settings
.setValue("meta_objs", i
);
308 void Session::save_settings(QSettings
&settings
) const
310 map
<string
, string
> dev_info
;
311 list
<string
> key_list
;
314 shared_ptr
<devices::HardwareDevice
> hw_device
=
315 dynamic_pointer_cast
< devices::HardwareDevice
>(device_
);
318 settings
.setValue("device_type", "hardware");
319 settings
.beginGroup("device");
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");
327 dev_info
= device_manager_
.get_device_info(device_
);
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()));
334 settings
.remove(QString::fromUtf8(key
.c_str()));
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());
350 shared_ptr
<devices::SessionFile
> sessionfile_device
=
351 dynamic_pointer_cast
<devices::SessionFile
>(device_
);
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()));
361 shared_ptr
<devices::InputFile
> inputfile_device
=
362 dynamic_pointer_cast
<devices::InputFile
>(device_
);
364 if (inputfile_device
) {
365 settings
.setValue("device_type", "inputfile");
366 settings
.beginGroup("device");
367 inputfile_device
->save_meta_to_settings(settings
);
372 save_setup(settings
);
376 void Session::restore_setup(QSettings
&settings
)
379 for (shared_ptr
<data::SignalBase
> base
: signalbases_
) {
380 settings
.beginGroup(base
->internal_name());
381 base
->restore_settings(settings
);
385 // Restore generated signals
386 int gen_signal_count
= settings
.value("generated_signals").toInt();
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
;
393 if (type
== SignalBase::MathChannel
)
394 signal
= make_shared
<data::MathSignal
>(*this);
396 qWarning() << tr("Can't restore generated signal of unknown type %1 (%2)") \
398 .arg(settings
.value("name").toString());
401 add_generated_signal(signal
);
402 signal
->restore_settings(settings
);
410 int decode_signal_count
= settings
.value("decode_signals").toInt();
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
);
421 int views
= settings
.value("views").toInt();
423 for (int i
= 0; i
< views
; i
++) {
424 settings
.beginGroup("view" + QString::number(i
));
427 views::ViewType type
= (views::ViewType
)settings
.value("type").toInt();
428 add_view(type
, this);
429 views_
.back()->restore_settings(settings
);
431 main_view_
->restore_settings(settings
);
436 // Restore meta objects like markers and cursors
437 int meta_objs
= settings
.value("meta_objs").toInt();
439 for (int i
= 0; i
< meta_objs
; i
++) {
440 settings
.beginGroup("meta_obj" + QString::number(i
));
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());
448 tv
= dynamic_pointer_cast
<views::trace::View
>(vb
);
450 const QString type
= settings
.value("type").toString();
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());
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
);
469 void Session::restore_settings(QSettings
&settings
)
471 shared_ptr
<devices::Device
> device
;
473 const QString device_type
= settings
.value("device_type").toString();
475 if (device_type
== "hardware") {
476 map
<string
, string
> dev_info
;
477 list
<string
> key_list
;
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");
487 for (string key
: key_list
) {
488 const QString k
= QString::fromStdString(key
);
489 if (!settings
.contains(k
))
492 const string value
= settings
.value(k
).toString().toStdString();
494 dev_info
.insert(make_pair(key
, value
));
497 if (dev_info
.count("model") > 0)
498 device
= device_manager_
.find_device_from_info(dev_info
);
506 restore_setup(settings
);
510 if ((device_type
== "sessionfile") || (device_type
== "inputfile")) {
511 if (device_type
== "sessionfile") {
512 settings
.beginGroup("device");
513 filename
= settings
.value("filename").toString();
516 if (QFileInfo(filename
).isReadable())
517 device
= make_shared
<devices::SessionFile
>(device_manager_
.context(),
518 filename
.toStdString());
521 if (device_type
== "inputfile") {
522 settings
.beginGroup("device");
523 device
= make_shared
<devices::InputFile
>(device_manager_
.context(),
531 restore_setup(settings
);
533 start_capture([](QString infoMessage
) {
534 // TODO Emulate noquote()
535 qDebug() << "Session error:" << infoMessage
; });
537 set_name(QString::fromStdString(
538 dynamic_pointer_cast
<devices::File
>(device
)->display_name(device_manager_
)));
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());
545 set_name(QFileInfo(filename
).fileName());
551 void Session::select_device(shared_ptr
<devices::Device
> device
)
557 set_default_device();
558 } catch (const QString
&e
) {
559 MainWindow::show_session_error(tr("Failed to select device"), e
);
563 void Session::set_device(shared_ptr
<devices::Device
> device
)
567 // Ensure we are not capturing before setting the device
575 // Revert name back to default name (e.g. "Session 1") as the data is gone
576 name_
= default_name_
;
579 // Remove all stored data and reset all views
580 for (shared_ptr
<views::ViewBase
> view
: views_
) {
581 view
->clear_signalbases();
583 view
->clear_decode_signals();
585 view
->reset_view_state();
588 for (SignalGroup
* group
: signal_groups_
) {
592 signal_groups_
.clear();
594 for (const shared_ptr
<data::SignalData
>& d
: all_signal_data_
)
597 all_signal_data_
.clear();
598 signalbases_
.clear();
599 cur_logic_segment_
.reset();
601 for (auto& entry
: cur_analog_segments_
) {
602 shared_ptr
<sigrok::Channel
>(entry
.first
).reset();
603 shared_ptr
<data::AnalogSegment
>(entry
.second
).reset();
610 device_
= move(device
);
614 } catch (const QString
&e
) {
616 MainWindow::show_session_error(tr("Failed to open device"), e
);
620 device_
->session()->add_datafeed_callback([=]
621 (shared_ptr
<sigrok::Device
> device
, shared_ptr
<Packet
> packet
) {
622 data_feed_in(device
, packet
);
631 void Session::set_default_device()
633 const list
< shared_ptr
<devices::HardwareDevice
> > &devices
=
634 device_manager_
.devices();
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
);
646 bool Session::using_file_device() const
648 shared_ptr
<devices::SessionFile
> sessionfile_device
=
649 dynamic_pointer_cast
<devices::SessionFile
>(device_
);
651 shared_ptr
<devices::InputFile
> inputfile_device
=
652 dynamic_pointer_cast
<devices::InputFile
>(device_
);
654 return (sessionfile_device
|| inputfile_device
);
658 * Convert generic options to data types that are specific to InputFormat.
660 * @param[in] user_spec Vector of tokenized words, string format.
661 * @param[in] fmt_opts Input format's options, result of InputFormat::options().
663 * @return Map of options suitable for InputFormat::create_input().
665 map
<string
, Glib::VariantBase
>
666 Session::input_format_options(vector
<string
> user_spec
,
667 map
<string
, shared_ptr
<Option
>> fmt_opts
)
669 map
<string
, Glib::VariantBase
> result
;
671 for (auto& entry
: user_spec
) {
673 * Split key=value specs. Accept entries without separator
674 * (for simplified boolean specifications).
677 size_t pos
= entry
.find("=");
678 if (pos
== std::string::npos
) {
682 key
= entry
.substr(0, pos
);
683 val
= entry
.substr(pos
+ 1);
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
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!";
699 shared_ptr
<Option
> opt
= found
->second
;
700 result
[key
] = opt
->parse_string(val
);
706 void Session::load_init_file(const string
&file_name
,
707 const string
&format
, const string
&setup_file_name
)
709 shared_ptr
<InputFormat
> input_format
;
710 map
<string
, Glib::VariantBase
> input_opts
;
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
)));
726 input_format
= (*iter
).second
;
727 input_opts
= input_format_options(user_opts
,
728 input_format
->options());
731 load_file(QString::fromStdString(file_name
), QString::fromStdString(setup_file_name
),
732 input_format
, input_opts
);
735 void Session::load_file(QString file_name
, QString setup_file_name
,
736 shared_ptr
<sigrok::InputFormat
> format
, const map
<string
, Glib::VariantBase
> &options
)
738 const QString
errorMessage(
739 QString("Failed to load file %1").arg(file_name
));
741 // In the absence of a caller's format spec, try to auto detect.
742 // Assume "sigrok session file" upon lookup miss.
744 format
= device_manager_
.context()->input_format_match(file_name
.toStdString());
747 set_device(shared_ptr
<devices::Device
>(
748 new devices::InputFile(
749 device_manager_
.context(),
750 file_name
.toStdString(),
753 set_device(shared_ptr
<devices::Device
>(
754 new devices::SessionFile(
755 device_manager_
.context(),
756 file_name
.toStdString())));
758 MainWindow::show_session_error(tr("Failed to load %1").arg(file_name
), e
.what());
759 set_default_device();
760 main_bar_
->update_device_list();
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");
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
);
776 main_bar_
->update_device_list();
778 start_capture([&, errorMessage
](QString infoMessage
) {
779 MainWindow::show_session_error(errorMessage
, infoMessage
); });
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());
785 set_name(QFileInfo(file_name
).fileName());
788 Session::capture_state
Session::get_capture_state() const
790 lock_guard
<mutex
> lock(sampling_mutex_
);
791 return capture_state_
;
794 void Session::start_capture(function
<void (const QString
)> error_handler
)
797 error_handler(tr("No active device set, can't start acquisition."));
803 // Check that at least one channel is enabled
804 const shared_ptr
<sigrok::Device
> sr_dev
= device_
->device();
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."));
816 for (const shared_ptr
<data::SignalData
>& d
: all_signal_data_
)
819 trigger_list_
.clear();
820 segment_sample_count_
.clear();
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_
);
828 name_
= default_name_
;
833 sampling_thread_
= std::thread(&Session::sample_thread_proc
, this, error_handler
);
836 void Session::stop_capture()
838 if (get_capture_state() != Stopped
)
841 // Check that sampling stopped
842 if (sampling_thread_
.joinable())
843 sampling_thread_
.join();
846 void Session::register_view(shared_ptr
<views::ViewBase
> view
)
851 views_
.push_back(view
);
853 // Add all device signals
856 // Add all other signals
857 vector
< shared_ptr
<data::SignalBase
> > view_signalbases
= view
->signalbases();
859 for (const shared_ptr
<data::SignalBase
>& signalbase
: signalbases_
) {
860 const int sb_exists
= count_if(
861 view_signalbases
.cbegin(), view_signalbases
.cend(),
862 [&](const shared_ptr
<data::SignalBase
> &sb
) {
863 return sb
== signalbase
;
866 // Add the signal to the view if it doesn't have it yet
868 switch (signalbase
->type()) {
869 case data::SignalBase::AnalogChannel
:
870 case data::SignalBase::LogicChannel
:
871 case data::SignalBase::MathChannel
:
872 view
->add_signalbase(signalbase
);
874 case data::SignalBase::DecodeChannel
:
876 view
->add_decode_signal(dynamic_pointer_cast
<data::DecodeSignal
>(signalbase
));
885 void Session::deregister_view(shared_ptr
<views::ViewBase
> view
)
887 views_
.erase(std::remove_if(views_
.begin(), views_
.end(),
888 [&](shared_ptr
<views::ViewBase
> v
) { return v
== view
; }),
891 if (views_
.empty()) {
894 // Without a view there can be no main bar
899 bool Session::has_view(shared_ptr
<views::ViewBase
> view
)
901 for (shared_ptr
<views::ViewBase
>& v
: views_
)
908 double Session::get_samplerate() const
910 double samplerate
= 0.0;
912 for (const shared_ptr
<pv::data::SignalData
>& d
: all_signal_data_
) {
914 const vector
< shared_ptr
<pv::data::Segment
> > segments
=
916 for (const shared_ptr
<pv::data::Segment
>& s
: segments
)
917 samplerate
= max(samplerate
, s
->samplerate());
919 // If there is no sample rate given we use samples as unit
920 if (samplerate
== 0.0)
926 uint32_t Session::get_highest_segment_id() const
928 return highest_segment_id_
;
931 uint64_t Session::get_segment_sample_count(uint32_t segment_id
) const
933 if (segment_id
< segment_sample_count_
.size())
934 return segment_sample_count_
[segment_id
];
939 vector
<util::Timestamp
> Session::get_triggers(uint32_t segment_id
) const
941 vector
<util::Timestamp
> result
;
943 for (const pair
<uint32_t, util::Timestamp
>& entry
: trigger_list_
)
944 if (entry
.first
== segment_id
)
945 result
.push_back(entry
.second
);
950 const vector
< shared_ptr
<data::SignalBase
> > Session::signalbases() const
955 uint32_t Session::get_signal_count(data::SignalBase::ChannelType type
) const
957 return count_if(signalbases_
.begin(), signalbases_
.end(),
958 [&] (shared_ptr
<SignalBase
> sb
) { return sb
->type() == type
; });
961 uint32_t Session::get_next_signal_index(data::SignalBase::ChannelType type
)
963 next_index_list_
[type
]++;
964 return next_index_list_
[type
];
967 void Session::add_generated_signal(shared_ptr
<data::SignalBase
> signal
)
969 signalbases_
.push_back(signal
);
971 for (shared_ptr
<views::ViewBase
>& view
: views_
)
972 view
->add_signalbase(signal
);
977 void Session::remove_generated_signal(shared_ptr
<data::SignalBase
> signal
)
982 signalbases_
.erase(std::remove_if(signalbases_
.begin(), signalbases_
.end(),
983 [&](shared_ptr
<data::SignalBase
> s
) { return s
== signal
; }),
986 for (shared_ptr
<views::ViewBase
>& view
: views_
)
987 view
->remove_signalbase(signal
);
993 shared_ptr
<data::DecodeSignal
> Session::add_decode_signal()
995 shared_ptr
<data::DecodeSignal
> signal
;
998 // Create the decode signal
999 signal
= make_shared
<data::DecodeSignal
>(*this);
1001 signalbases_
.push_back(signal
);
1003 // Add the decode signal to all views
1004 for (shared_ptr
<views::ViewBase
>& view
: views_
)
1005 view
->add_decode_signal(signal
);
1006 } catch (runtime_error
& e
) {
1007 remove_decode_signal(signal
);
1016 void Session::remove_decode_signal(shared_ptr
<data::DecodeSignal
> signal
)
1021 signalbases_
.erase(std::remove_if(signalbases_
.begin(), signalbases_
.end(),
1022 [&](shared_ptr
<data::SignalBase
> s
) { return s
== signal
; }),
1023 signalbases_
.end());
1025 for (shared_ptr
<views::ViewBase
>& view
: views_
)
1026 view
->remove_decode_signal(signal
);
1032 bool Session::all_segments_complete(uint32_t segment_id
) const
1034 bool all_complete
= true;
1036 for (const shared_ptr
<data::SignalBase
>& base
: signalbases_
)
1037 if (!base
->segment_is_complete(segment_id
))
1038 all_complete
= false;
1040 return all_complete
;
1043 MetadataObjManager
* Session::metadata_obj_manager()
1045 return &metadata_obj_manager_
;
1048 void Session::set_capture_state(capture_state state
)
1050 if (state
== capture_state_
)
1053 if (state
== Running
)
1054 acq_time_
.restart();
1055 if (state
== Stopped
)
1056 qDebug("Acquisition took %.2f s", acq_time_
.elapsed() / 1000.);
1059 lock_guard
<mutex
> lock(sampling_mutex_
);
1060 capture_state_
= state
;
1063 capture_state_changed(state
);
1066 void Session::update_signals()
1069 signalbases_
.clear();
1070 logic_data_
.reset();
1071 for (shared_ptr
<views::ViewBase
>& view
: views_
) {
1072 view
->clear_signalbases();
1073 #ifdef ENABLE_DECODE
1074 view
->clear_decode_signals();
1080 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1082 const shared_ptr
<sigrok::Device
> sr_dev
= device_
->device();
1084 signalbases_
.clear();
1085 logic_data_
.reset();
1086 for (shared_ptr
<views::ViewBase
>& view
: views_
) {
1087 view
->clear_signalbases();
1088 #ifdef ENABLE_DECODE
1089 view
->clear_decode_signals();
1095 // Detect what data types we will receive
1096 auto channels
= sr_dev
->channels();
1097 unsigned int logic_channel_count
= count_if(
1098 channels
.begin(), channels
.end(),
1099 [] (shared_ptr
<Channel
> channel
) {
1100 return channel
->type() == sigrok::ChannelType::LOGIC
; });
1102 // Create a common data container for the logic signalbases
1104 lock_guard
<recursive_mutex
> data_lock(data_mutex_
);
1106 if (logic_channel_count
== 0) {
1107 logic_data_
.reset();
1108 } else if (!logic_data_
||
1109 logic_data_
->num_channels() != logic_channel_count
) {
1110 logic_data_
.reset(new data::Logic(logic_channel_count
));
1111 assert(logic_data_
);
1115 // Create signalbases if necessary
1116 for (auto channel
: sr_dev
->channels()) {
1118 // Try to find the channel in the list of existing signalbases
1119 const auto iter
= find_if(signalbases_
.cbegin(), signalbases_
.cend(),
1120 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
->channel() == channel
; });
1122 // Not found, let's make a signalbase for it
1123 if (iter
== signalbases_
.cend()) {
1124 shared_ptr
<SignalBase
> signalbase
;
1125 switch(channel
->type()->id()) {
1126 case SR_CHANNEL_LOGIC
:
1127 signalbase
= make_shared
<data::SignalBase
>(channel
, data::SignalBase::LogicChannel
);
1128 signalbases_
.push_back(signalbase
);
1130 all_signal_data_
.insert(logic_data_
);
1131 signalbase
->set_data(logic_data_
);
1133 connect(this, SIGNAL(capture_state_changed(int)),
1134 signalbase
.get(), SLOT(on_capture_state_changed(int)));
1137 case SR_CHANNEL_ANALOG
:
1138 signalbase
= make_shared
<data::SignalBase
>(channel
, data::SignalBase::AnalogChannel
);
1139 signalbases_
.push_back(signalbase
);
1141 shared_ptr
<data::Analog
> data(new data::Analog());
1142 all_signal_data_
.insert(data
);
1143 signalbase
->set_data(data
);
1145 connect(this, SIGNAL(capture_state_changed(int)),
1146 signalbase
.get(), SLOT(on_capture_state_changed(int)));
1152 // Create and assign default signal groups if needed
1153 if (signal_groups_
.empty()) {
1154 for (auto& entry
: sr_dev
->channel_groups()) {
1155 const shared_ptr
<sigrok::ChannelGroup
>& group
= entry
.second
;
1157 if (group
->channels().size() <= 1)
1160 SignalGroup
* sg
= new SignalGroup(QString::fromStdString(entry
.first
));
1161 for (const shared_ptr
<sigrok::Channel
>& channel
: group
->channels()) {
1162 for (shared_ptr
<data::SignalBase
> s
: signalbases_
) {
1163 if (s
->channel() == channel
) {
1164 sg
->append_signal(s
);
1169 signal_groups_
.emplace_back(sg
);
1174 for (shared_ptr
<views::ViewBase
>& viewbase
: views_
) {
1175 vector
< shared_ptr
<SignalBase
> > view_signalbases
=
1176 viewbase
->signalbases();
1178 // Add all non-decode signalbases that don't yet exist in the view
1179 for (shared_ptr
<SignalBase
>& session_sb
: signalbases_
) {
1180 if (session_sb
->type() == SignalBase::DecodeChannel
)
1183 const auto iter
= find_if(view_signalbases
.cbegin(), view_signalbases
.cend(),
1184 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
== session_sb
; });
1186 if (iter
== view_signalbases
.cend())
1187 viewbase
->add_signalbase(session_sb
);
1190 // Remove all non-decode signalbases that no longer exist
1191 for (shared_ptr
<SignalBase
>& view_sb
: view_signalbases
) {
1192 if (view_sb
->type() == SignalBase::DecodeChannel
)
1195 const auto iter
= find_if(signalbases_
.cbegin(), signalbases_
.cend(),
1196 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
== view_sb
; });
1198 if (iter
== signalbases_
.cend())
1199 viewbase
->remove_signalbase(view_sb
);
1206 shared_ptr
<data::SignalBase
> Session::signalbase_from_channel(
1207 shared_ptr
<sigrok::Channel
> channel
) const
1209 for (shared_ptr
<data::SignalBase
> sig
: signalbases_
) {
1211 if (sig
->channel() == channel
)
1214 return shared_ptr
<data::SignalBase
>();
1217 void Session::sample_thread_proc(function
<void (const QString
)> error_handler
)
1219 assert(error_handler
);
1222 pipeline_
= Pipeline::create();
1224 source_
= ElementFactory::create_element("filesrc", "source");
1225 sink_
= RefPtr
<AppSink
>::cast_dynamic(ElementFactory::create_element("appsink", "sink"));
1227 pipeline_
->add(source_
)->add(sink_
);
1228 source_
->link(sink_
);
1230 source_
->set_property("location", Glib::ustring("/tmp/dummy_binary"));
1232 sink_
->set_property("emit-signals", TRUE
);
1233 sink_
->signal_new_sample().connect(sigc::mem_fun(*this, &Session::on_gst_new_sample
));
1235 // Get the bus from the pipeline and add a bus watch to the default main context
1236 RefPtr
<Bus
> bus
= pipeline_
->get_bus();
1237 bus
->add_watch(sigc::mem_fun(this, &Session::on_gst_bus_message
));
1239 // Start pipeline and Wait until it finished processing
1240 pipeline_done_interrupt_
= false;
1241 pipeline_
->set_state(Gst::STATE_PLAYING
);
1243 unique_lock
<mutex
> pipeline_done_lock_(pipeline_done_mutex_
);
1244 pipeline_done_cond_
.wait(pipeline_done_lock_
);
1246 // Let the pipeline free all resources
1247 pipeline_
->set_state(Gst::STATE_NULL
);
1254 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1255 } catch (Error
& e
) {
1256 cur_samplerate_
= 0;
1259 out_of_memory_
= false;
1262 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1263 cur_logic_segment_
.reset();
1264 cur_analog_segments_
.clear();
1265 for (shared_ptr
<data::SignalBase
> sb
: signalbases_
)
1266 sb
->clear_sample_data();
1268 highest_segment_id_
= -1;
1269 frame_began_
= false;
1273 } catch (Error
& e
) {
1274 error_handler(e
.what());
1278 set_capture_state(device_
->session()->trigger() ?
1279 AwaitingTrigger
: Running
);
1283 } catch (Error
& e
) {
1284 error_handler(e
.what());
1285 set_capture_state(Stopped
);
1287 } catch (QString
& e
) {
1289 set_capture_state(Stopped
);
1293 set_capture_state(Stopped
);
1295 // Confirm that SR_DF_END was received
1296 if (cur_logic_segment_
)
1297 qDebug() << "WARNING: SR_DF_END was not received.";
1300 // Optimize memory usage
1301 free_unused_memory();
1303 // We now have unsaved data unless we just "captured" from a file
1304 shared_ptr
<devices::File
> file_device
=
1305 dynamic_pointer_cast
<devices::File
>(device_
);
1308 data_saved_
= false;
1311 error_handler(tr("Out of memory, acquisition stopped."));
1314 void Session::free_unused_memory()
1316 for (const shared_ptr
<data::SignalData
>& data
: all_signal_data_
) {
1317 const vector
< shared_ptr
<data::Segment
> > segments
= data
->segments();
1319 for (const shared_ptr
<data::Segment
>& segment
: segments
)
1320 segment
->free_unused_memory();
1324 void Session::signal_new_segment()
1326 int new_segment_id
= 0;
1328 if ((cur_logic_segment_
!= nullptr) || !cur_analog_segments_
.empty()) {
1330 // Determine new frame/segment number, assuming that all
1331 // signals have the same number of frames/segments
1332 if (cur_logic_segment_
) {
1333 new_segment_id
= logic_data_
->get_segment_count() - 1;
1335 shared_ptr
<sigrok::Channel
> any_channel
=
1336 (*cur_analog_segments_
.begin()).first
;
1338 shared_ptr
<data::SignalBase
> base
= signalbase_from_channel(any_channel
);
1341 shared_ptr
<data::Analog
> data(base
->analog_data());
1344 new_segment_id
= data
->get_segment_count() - 1;
1348 if (new_segment_id
> highest_segment_id_
) {
1349 highest_segment_id_
= new_segment_id
;
1350 segment_sample_count_
.emplace_back(0);
1351 new_segment(highest_segment_id_
);
1355 void Session::signal_segment_completed()
1359 for (const shared_ptr
<data::SignalBase
>& signalbase
: signalbases_
) {
1360 // We only care about analog and logic channels, not derived ones
1361 if (signalbase
->type() == data::SignalBase::AnalogChannel
) {
1362 segment_id
= signalbase
->analog_data()->get_segment_count() - 1;
1366 if (signalbase
->type() == data::SignalBase::LogicChannel
) {
1367 segment_id
= signalbase
->logic_data()->get_segment_count() - 1;
1372 if (segment_id
>= 0)
1373 segment_completed(segment_id
);
1377 bool Session::on_gst_bus_message(const Glib::RefPtr
<Gst::Bus
>& bus
, const Glib::RefPtr
<Gst::Message
>& message
)
1381 if ((message
->get_source() == pipeline_
) && \
1382 ((message
->get_message_type() == Gst::MESSAGE_EOS
)))
1383 pipeline_done_cond_
.notify_one();
1385 // TODO Also evaluate MESSAGE_STREAM_STATUS to receive error notifications
1390 Gst::FlowReturn
Session::on_gst_new_sample()
1392 RefPtr
<Gst::Sample
> sample
= sink_
->pull_sample();
1393 RefPtr
<Gst::Buffer
> buf
= sample
->get_buffer();
1395 for (uint32_t block_id
= 0; block_id
< buf
->n_memory(); block_id
++) {
1396 RefPtr
<Gst::Memory
> buf_mem
= buf
->get_memory(block_id
);
1397 Gst::MapInfo mapinfo
;
1398 buf_mem
->map(mapinfo
, Gst::MAP_READ
);
1400 shared_ptr
<sigrok::Packet
> logic_packet
=
1401 sr_context
->create_logic_packet(mapinfo
.get_data(), buf
->get_size(), 1);
1404 feed_in_logic(dynamic_pointer_cast
<sigrok::Logic
>(logic_packet
->payload()));
1405 } catch (bad_alloc
&) {
1406 out_of_memory_
= true;
1408 buf_mem
->unmap(mapinfo
);
1409 return Gst::FLOW_ERROR
;
1412 buf_mem
->unmap(mapinfo
);
1415 return Gst::FLOW_OK
;
1419 void Session::feed_in_header()
1421 // Nothing to do here for now
1424 void Session::feed_in_meta(shared_ptr
<Meta
> meta
)
1426 for (auto& entry
: meta
->config()) {
1427 switch (entry
.first
->id()) {
1428 case SR_CONF_SAMPLERATE
:
1429 cur_samplerate_
= g_variant_get_uint64(entry
.second
.gobj());
1432 qDebug() << "Received meta data key" << entry
.first
->id() << ", ignoring.";
1440 void Session::feed_in_trigger()
1442 // The channel containing most samples should be most accurate
1443 uint64_t sample_count
= 0;
1446 for (const shared_ptr
<pv::data::SignalData
>& d
: all_signal_data_
) {
1448 uint64_t temp_count
= 0;
1450 const vector
< shared_ptr
<pv::data::Segment
> > segments
=
1452 for (const shared_ptr
<pv::data::Segment
> &s
: segments
)
1453 temp_count
+= s
->get_sample_count();
1455 if (temp_count
> sample_count
)
1456 sample_count
= temp_count
;
1460 uint32_t segment_id
= 0; // Default segment when no frames are used
1462 // If a frame began, we'd ideally be able to use the highest segment ID for
1463 // the trigger. However, as new segments are only created when logic or
1464 // analog data comes in, this doesn't work if the trigger appears right
1465 // after the beginning of the frame, before any sample data.
1466 // For this reason, we use highest segment ID + 1 if no sample data came in
1467 // yet and the highest segment ID otherwise.
1469 segment_id
= highest_segment_id_
;
1470 if (!cur_logic_segment_
&& (cur_analog_segments_
.size() == 0))
1474 // TODO Create timestamp from segment start time + segment's current sample count
1475 util::Timestamp timestamp
= sample_count
/ get_samplerate();
1476 trigger_list_
.emplace_back(segment_id
, timestamp
);
1477 trigger_event(segment_id
, timestamp
);
1480 void Session::feed_in_frame_begin()
1482 frame_began_
= true;
1485 void Session::feed_in_frame_end()
1491 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1493 if (cur_logic_segment_
)
1494 cur_logic_segment_
->set_complete();
1496 for (auto& entry
: cur_analog_segments_
) {
1497 shared_ptr
<data::AnalogSegment
> segment
= entry
.second
;
1498 segment
->set_complete();
1501 cur_logic_segment_
.reset();
1502 cur_analog_segments_
.clear();
1505 frame_began_
= false;
1507 signal_segment_completed();
1510 void Session::feed_in_logic(shared_ptr
<sigrok::Logic
> logic
)
1512 if (logic
->data_length() == 0) {
1513 qDebug() << "WARNING: Received logic packet with 0 samples.";
1517 if (logic
->unit_size() > 8)
1518 throw QString(tr("Can't handle more than 64 logic channels."));
1520 if (!cur_samplerate_
)
1522 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1523 } catch (Error
& e
) {
1527 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1530 // The only reason logic_data_ would not have been created is
1531 // if it was not possible to determine the signals when the
1532 // device was created.
1536 if (!cur_logic_segment_
) {
1537 // This could be the first packet after a trigger
1538 set_capture_state(Running
);
1540 // Create a new data segment
1541 cur_logic_segment_
= make_shared
<data::LogicSegment
>(
1542 *logic_data_
, logic_data_
->get_segment_count(),
1543 logic
->unit_size(), cur_samplerate_
);
1544 logic_data_
->push_segment(cur_logic_segment_
);
1546 signal_new_segment();
1549 cur_logic_segment_
->append_payload(logic
);
1551 segment_sample_count_
[highest_segment_id_
] =
1552 max(segment_sample_count_
[highest_segment_id_
], cur_logic_segment_
->get_sample_count());
1557 void Session::feed_in_analog(shared_ptr
<sigrok::Analog
> analog
)
1559 if (analog
->num_samples() == 0) {
1560 qDebug() << "WARNING: Received analog packet with 0 samples.";
1564 if (!cur_samplerate_
)
1566 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1567 } catch (Error
& e
) {
1571 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1573 const vector
<shared_ptr
<Channel
>> channels
= analog
->channels();
1574 bool sweep_beginning
= false;
1576 unique_ptr
<float[]> data(new float[analog
->num_samples() * channels
.size()]);
1577 analog
->get_data_as_float(data
.get());
1579 if (signalbases_
.empty())
1582 float *channel_data
= data
.get();
1583 for (auto& channel
: channels
) {
1584 shared_ptr
<data::AnalogSegment
> segment
;
1586 // Try to get the segment of the channel
1587 const map
< shared_ptr
<Channel
>, shared_ptr
<data::AnalogSegment
> >::
1588 iterator iter
= cur_analog_segments_
.find(channel
);
1589 if (iter
!= cur_analog_segments_
.end())
1590 segment
= (*iter
).second
;
1592 // If no segment was found, this means we haven't
1593 // created one yet. i.e. this is the first packet
1594 // in the sweep containing this segment.
1595 sweep_beginning
= true;
1597 // Find the analog data associated with the channel
1598 shared_ptr
<data::SignalBase
> base
= signalbase_from_channel(channel
);
1601 shared_ptr
<data::Analog
> data(base
->analog_data());
1604 // Create a segment, keep it in the maps of channels
1605 segment
= make_shared
<data::AnalogSegment
>(
1606 *data
, data
->get_segment_count(), cur_samplerate_
);
1607 cur_analog_segments_
[channel
] = segment
;
1609 // Push the segment into the analog data.
1610 data
->push_segment(segment
);
1612 signal_new_segment();
1617 // Append the samples in the segment
1618 segment
->append_interleaved_samples(channel_data
++, analog
->num_samples(),
1621 segment_sample_count_
[highest_segment_id_
] =
1622 max(segment_sample_count_
[highest_segment_id_
], segment
->get_sample_count());
1625 if (sweep_beginning
) {
1626 // This could be the first packet after a trigger
1627 set_capture_state(Running
);
1633 void Session::data_feed_in(shared_ptr
<sigrok::Device
> device
,
1634 shared_ptr
<Packet
> packet
)
1639 assert(device
== device_
->device());
1642 switch (packet
->type()->id()) {
1648 feed_in_meta(dynamic_pointer_cast
<Meta
>(packet
->payload()));
1657 feed_in_logic(dynamic_pointer_cast
<Logic
>(packet
->payload()));
1658 } catch (bad_alloc
&) {
1659 out_of_memory_
= true;
1666 feed_in_analog(dynamic_pointer_cast
<Analog
>(packet
->payload()));
1667 } catch (bad_alloc
&) {
1668 out_of_memory_
= true;
1673 case SR_DF_FRAME_BEGIN
:
1674 feed_in_frame_begin();
1677 case SR_DF_FRAME_END
:
1678 feed_in_frame_end();
1682 // Strictly speaking, this is performed when a frame end marker was
1683 // received, so there's no point doing this again. However, not all
1684 // devices use frames, and for those devices, we need to do it here.
1686 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1688 if (cur_logic_segment_
)
1689 cur_logic_segment_
->set_complete();
1691 for (auto& entry
: cur_analog_segments_
) {
1692 shared_ptr
<data::AnalogSegment
> segment
= entry
.second
;
1693 segment
->set_complete();
1696 cur_logic_segment_
.reset();
1697 cur_analog_segments_
.clear();
1706 void Session::on_data_saved()
1711 #ifdef ENABLE_DECODE
1712 void Session::on_new_decoders_selected(vector
<const srd_decoder
*> decoders
)
1714 assert(decoders
.size() > 0);
1716 shared_ptr
<data::DecodeSignal
> signal
= add_decode_signal();
1719 for (unsigned int i
= 0; i
< decoders
.size(); i
++) {
1720 const srd_decoder
* d
= decoders
[i
];
1721 signal
->stack_decoder(d
, !(i
< decoders
.size() - 1));