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/>.
30 #include "devicemanager.hpp"
31 #include "mainwindow.hpp"
32 #include "session.hpp"
35 #include "data/analog.hpp"
36 #include "data/analogsegment.hpp"
37 #include "data/decode/decoder.hpp"
38 #include "data/logic.hpp"
39 #include "data/logicsegment.hpp"
40 #include "data/signalbase.hpp"
42 #include "devices/hardwaredevice.hpp"
43 #include "devices/inputfile.hpp"
44 #include "devices/sessionfile.hpp"
46 #include "toolbars/mainbar.hpp"
48 #include "views/trace/analogsignal.hpp"
49 #include "views/trace/decodetrace.hpp"
50 #include "views/trace/logicsignal.hpp"
51 #include "views/trace/signal.hpp"
52 #include "views/trace/view.hpp"
54 #include <libsigrokcxx/libsigrokcxx.hpp>
57 #include <gstreamermm.h>
58 #include <libsigrokflow/libsigrokflow.hpp>
62 #include <libsigrokdecode/libsigrokdecode.h>
63 #include "data/decodesignal.hpp"
67 using std::dynamic_pointer_cast
;
71 using std::lock_guard
;
73 using std::make_shared
;
79 using std::recursive_mutex
;
80 using std::runtime_error
;
81 using std::shared_ptr
;
84 using std::unique_lock
;
86 using std::unique_ptr
;
90 using sigrok::Channel
;
91 using sigrok::ConfigKey
;
92 using sigrok::DatafeedCallbackFunction
;
94 using sigrok::InputFormat
;
98 using sigrok::Session
;
100 using Glib::VariantBase
;
104 using Gst::ElementFactory
;
108 using pv::data::SignalGroup
;
109 using pv::util::Timestamp
;
110 using pv::views::trace::Signal
;
111 using pv::views::trace::AnalogSignal
;
112 using pv::views::trace::LogicSignal
;
116 shared_ptr
<sigrok::Context
> Session::sr_context
;
118 Session::Session(DeviceManager
&device_manager
, QString name
) :
119 shutting_down_(false),
120 device_manager_(device_manager
),
123 capture_state_(Stopped
),
131 shutting_down_
= true;
133 // Stop and join to the thread
136 for (SignalGroup
* group
: signal_groups_
) {
142 DeviceManager
& Session::device_manager()
144 return device_manager_
;
147 const DeviceManager
& Session::device_manager() const
149 return device_manager_
;
152 shared_ptr
<sigrok::Session
> Session::session() const
155 return shared_ptr
<sigrok::Session
>();
156 return device_
->session();
159 shared_ptr
<devices::Device
> Session::device() const
164 QString
Session::name() const
169 void Session::set_name(QString name
)
171 if (default_name_
.isEmpty())
172 default_name_
= name
;
179 const vector
< shared_ptr
<views::ViewBase
> > Session::views() const
184 shared_ptr
<views::ViewBase
> Session::main_view() const
189 void Session::set_main_bar(shared_ptr
<pv::toolbars::MainBar
> main_bar
)
191 main_bar_
= main_bar
;
194 shared_ptr
<pv::toolbars::MainBar
> Session::main_bar() const
199 bool Session::data_saved() const
204 void Session::save_setup(QSettings
&settings
) const
208 // Save channels and decoders
209 for (const shared_ptr
<data::SignalBase
>& base
: signalbases_
) {
211 if (base
->is_decode_signal()) {
212 settings
.beginGroup("decode_signal" + QString::number(i
++));
213 base
->save_settings(settings
);
218 settings
.beginGroup(base
->internal_name());
219 base
->save_settings(settings
);
224 settings
.setValue("decode_signals", i
);
226 // Save view states and their signal settings
227 // Note: main_view must be saved as view0
229 settings
.beginGroup("view" + QString::number(i
++));
230 main_view_
->save_settings(settings
);
233 for (const shared_ptr
<views::ViewBase
>& view
: views_
) {
234 if (view
!= main_view_
) {
235 settings
.beginGroup("view" + QString::number(i
++));
236 settings
.setValue("type", view
->get_type());
237 view
->save_settings(settings
);
242 settings
.setValue("views", i
);
246 for (const shared_ptr
<views::ViewBase
>& vb
: views_
) {
247 shared_ptr
<views::trace::View
> tv
= dynamic_pointer_cast
<views::trace::View
>(vb
);
249 for (const shared_ptr
<views::trace::TimeItem
>& time_item
: tv
->time_items()) {
251 const shared_ptr
<views::trace::Flag
> flag
=
252 dynamic_pointer_cast
<views::trace::Flag
>(time_item
);
254 if (!flag
->enabled())
257 settings
.beginGroup("meta_obj" + QString::number(i
++));
258 settings
.setValue("type", "time_marker");
259 settings
.setValue("assoc_view", view_id
);
260 GlobalSettings::store_timestamp(settings
, "time", flag
->time());
261 settings
.setValue("text", flag
->get_text());
266 if (tv
->cursors_shown()) {
267 settings
.beginGroup("meta_obj" + QString::number(i
++));
268 settings
.setValue("type", "selection");
269 settings
.setValue("assoc_view", view_id
);
270 const shared_ptr
<views::trace::CursorPair
> cp
= tv
->cursors();
271 GlobalSettings::store_timestamp(settings
, "start_time", cp
->first()->time());
272 GlobalSettings::store_timestamp(settings
, "end_time", cp
->second()->time());
280 settings
.setValue("meta_objs", i
);
283 void Session::save_settings(QSettings
&settings
) const
285 map
<string
, string
> dev_info
;
286 list
<string
> key_list
;
289 shared_ptr
<devices::HardwareDevice
> hw_device
=
290 dynamic_pointer_cast
< devices::HardwareDevice
>(device_
);
293 settings
.setValue("device_type", "hardware");
294 settings
.beginGroup("device");
296 key_list
.emplace_back("vendor");
297 key_list
.emplace_back("model");
298 key_list
.emplace_back("version");
299 key_list
.emplace_back("serial_num");
300 key_list
.emplace_back("connection_id");
302 dev_info
= device_manager_
.get_device_info(device_
);
304 for (string
& key
: key_list
) {
305 if (dev_info
.count(key
))
306 settings
.setValue(QString::fromUtf8(key
.c_str()),
307 QString::fromUtf8(dev_info
.at(key
).c_str()));
309 settings
.remove(QString::fromUtf8(key
.c_str()));
315 shared_ptr
<devices::SessionFile
> sessionfile_device
=
316 dynamic_pointer_cast
<devices::SessionFile
>(device_
);
318 if (sessionfile_device
) {
319 settings
.setValue("device_type", "sessionfile");
320 settings
.beginGroup("device");
321 settings
.setValue("filename", QString::fromStdString(
322 sessionfile_device
->full_name()));
326 shared_ptr
<devices::InputFile
> inputfile_device
=
327 dynamic_pointer_cast
<devices::InputFile
>(device_
);
329 if (inputfile_device
) {
330 settings
.setValue("device_type", "inputfile");
331 settings
.beginGroup("device");
332 inputfile_device
->save_meta_to_settings(settings
);
336 save_setup(settings
);
340 void Session::restore_setup(QSettings
&settings
)
343 for (shared_ptr
<data::SignalBase
> base
: signalbases_
) {
344 settings
.beginGroup(base
->internal_name());
345 base
->restore_settings(settings
);
351 int decode_signals
= settings
.value("decode_signals").toInt();
353 for (int i
= 0; i
< decode_signals
; i
++) {
354 settings
.beginGroup("decode_signal" + QString::number(i
));
355 shared_ptr
<data::DecodeSignal
> signal
= add_decode_signal();
356 signal
->restore_settings(settings
);
362 int views
= settings
.value("views").toInt();
364 for (int i
= 0; i
< views
; i
++) {
365 settings
.beginGroup("view" + QString::number(i
));
368 views::ViewType type
= (views::ViewType
)settings
.value("type").toInt();
369 add_view(type
, this);
370 views_
.back()->restore_settings(settings
);
372 main_view_
->restore_settings(settings
);
377 // Restore meta objects like markers and cursors
378 int meta_objs
= settings
.value("meta_objs").toInt();
380 for (int i
= 0; i
< meta_objs
; i
++) {
381 settings
.beginGroup("meta_obj" + QString::number(i
));
383 shared_ptr
<views::ViewBase
> vb
;
384 shared_ptr
<views::trace::View
> tv
;
385 if (settings
.contains("assoc_view"))
386 vb
= views_
.at(settings
.value("assoc_view").toInt());
389 tv
= dynamic_pointer_cast
<views::trace::View
>(vb
);
391 const QString type
= settings
.value("type").toString();
393 if ((type
== "time_marker") && tv
) {
394 Timestamp ts
= GlobalSettings::restore_timestamp(settings
, "time");
395 shared_ptr
<views::trace::Flag
> flag
= tv
->add_flag(ts
);
396 flag
->set_text(settings
.value("text").toString());
399 if ((type
== "selection") && tv
) {
400 Timestamp start
= GlobalSettings::restore_timestamp(settings
, "start_time");
401 Timestamp end
= GlobalSettings::restore_timestamp(settings
, "end_time");
402 tv
->set_cursors(start
, end
);
410 void Session::restore_settings(QSettings
&settings
)
412 shared_ptr
<devices::Device
> device
;
414 const QString device_type
= settings
.value("device_type").toString();
416 if (device_type
== "hardware") {
417 map
<string
, string
> dev_info
;
418 list
<string
> key_list
;
420 // Re-select last used device if possible but only if it's not demo
421 settings
.beginGroup("device");
422 key_list
.emplace_back("vendor");
423 key_list
.emplace_back("model");
424 key_list
.emplace_back("version");
425 key_list
.emplace_back("serial_num");
426 key_list
.emplace_back("connection_id");
428 for (string key
: key_list
) {
429 const QString k
= QString::fromStdString(key
);
430 if (!settings
.contains(k
))
433 const string value
= settings
.value(k
).toString().toStdString();
435 dev_info
.insert(make_pair(key
, value
));
438 if (dev_info
.count("model") > 0)
439 device
= device_manager_
.find_device_from_info(dev_info
);
447 if ((device_type
== "sessionfile") || (device_type
== "inputfile")) {
448 if (device_type
== "sessionfile") {
449 settings
.beginGroup("device");
450 const QString filename
= settings
.value("filename").toString();
453 if (QFileInfo(filename
).isReadable()) {
454 device
= make_shared
<devices::SessionFile
>(device_manager_
.context(),
455 filename
.toStdString());
459 if (device_type
== "inputfile") {
460 settings
.beginGroup("device");
461 device
= make_shared
<devices::InputFile
>(device_manager_
.context(),
469 start_capture([](QString infoMessage
) {
470 // TODO Emulate noquote()
471 qDebug() << "Session error:" << infoMessage
; });
473 set_name(QString::fromStdString(
474 dynamic_pointer_cast
<devices::File
>(device
)->display_name(device_manager_
)));
479 restore_setup(settings
);
482 void Session::select_device(shared_ptr
<devices::Device
> device
)
488 set_default_device();
489 } catch (const QString
&e
) {
490 MainWindow::show_session_error(tr("Failed to select device"), e
);
494 void Session::set_device(shared_ptr
<devices::Device
> device
)
498 // Ensure we are not capturing before setting the device
506 // Revert name back to default name (e.g. "Session 1") as the data is gone
507 name_
= default_name_
;
510 // Remove all stored data and reset all views
511 for (shared_ptr
<views::ViewBase
> view
: views_
) {
512 view
->clear_signalbases();
514 view
->clear_decode_signals();
516 view
->reset_view_state();
519 for (SignalGroup
* group
: signal_groups_
) {
523 signal_groups_
.clear();
525 for (const shared_ptr
<data::SignalData
>& d
: all_signal_data_
)
528 all_signal_data_
.clear();
529 signalbases_
.clear();
530 cur_logic_segment_
.reset();
532 for (auto& entry
: cur_analog_segments_
) {
533 shared_ptr
<sigrok::Channel
>(entry
.first
).reset();
534 shared_ptr
<data::AnalogSegment
>(entry
.second
).reset();
541 device_
= move(device
);
545 } catch (const QString
&e
) {
547 MainWindow::show_session_error(tr("Failed to open device"), e
);
551 device_
->session()->add_datafeed_callback([=]
552 (shared_ptr
<sigrok::Device
> device
, shared_ptr
<Packet
> packet
) {
553 data_feed_in(device
, packet
);
562 void Session::set_default_device()
564 const list
< shared_ptr
<devices::HardwareDevice
> > &devices
=
565 device_manager_
.devices();
570 // Try and find the demo device and select that by default
571 const auto iter
= find_if(devices
.begin(), devices
.end(),
572 [] (const shared_ptr
<devices::HardwareDevice
> &d
) {
573 return d
->hardware_device()->driver()->name() == "demo"; });
574 set_device((iter
== devices
.end()) ? devices
.front() : *iter
);
577 bool Session::using_file_device() const
579 shared_ptr
<devices::SessionFile
> sessionfile_device
=
580 dynamic_pointer_cast
<devices::SessionFile
>(device_
);
582 shared_ptr
<devices::InputFile
> inputfile_device
=
583 dynamic_pointer_cast
<devices::InputFile
>(device_
);
585 return (sessionfile_device
|| inputfile_device
);
589 * Convert generic options to data types that are specific to InputFormat.
591 * @param[in] user_spec Vector of tokenized words, string format.
592 * @param[in] fmt_opts Input format's options, result of InputFormat::options().
594 * @return Map of options suitable for InputFormat::create_input().
596 map
<string
, Glib::VariantBase
>
597 Session::input_format_options(vector
<string
> user_spec
,
598 map
<string
, shared_ptr
<Option
>> fmt_opts
)
600 map
<string
, Glib::VariantBase
> result
;
602 for (auto& entry
: user_spec
) {
604 * Split key=value specs. Accept entries without separator
605 * (for simplified boolean specifications).
608 size_t pos
= entry
.find("=");
609 if (pos
== std::string::npos
) {
613 key
= entry
.substr(0, pos
);
614 val
= entry
.substr(pos
+ 1);
618 * Skip user specifications that are not a member of the
619 * format's set of supported options. Have the text input
620 * spec converted to the required input format specific
623 auto found
= fmt_opts
.find(key
);
624 if (found
== fmt_opts
.end())
626 shared_ptr
<Option
> opt
= found
->second
;
627 result
[key
] = opt
->parse_string(val
);
633 void Session::load_init_file(const string
&file_name
,
634 const string
&format
, const string
&setup_file_name
)
636 shared_ptr
<InputFormat
> input_format
;
637 map
<string
, Glib::VariantBase
> input_opts
;
639 if (!format
.empty()) {
640 const map
<string
, shared_ptr
<InputFormat
> > formats
=
641 device_manager_
.context()->input_formats();
642 auto user_opts
= pv::util::split_string(format
, ":");
643 string user_name
= user_opts
.front();
644 user_opts
.erase(user_opts
.begin());
645 const auto iter
= find_if(formats
.begin(), formats
.end(),
646 [&](const pair
<string
, shared_ptr
<InputFormat
> > f
) {
647 return f
.first
== user_name
; });
648 if (iter
== formats
.end()) {
649 MainWindow::show_session_error(tr("Error"),
650 tr("Unexpected input format: %s").arg(QString::fromStdString(format
)));
653 input_format
= (*iter
).second
;
654 input_opts
= input_format_options(user_opts
,
655 input_format
->options());
658 load_file(QString::fromStdString(file_name
), QString::fromStdString(setup_file_name
),
659 input_format
, input_opts
);
662 void Session::load_file(QString file_name
, QString setup_file_name
,
663 shared_ptr
<sigrok::InputFormat
> format
, const map
<string
, Glib::VariantBase
> &options
)
665 const QString
errorMessage(
666 QString("Failed to load file %1").arg(file_name
));
668 // In the absence of a caller's format spec, try to auto detect.
669 // Assume "sigrok session file" upon lookup miss.
671 format
= device_manager_
.context()->input_format_match(file_name
.toStdString());
674 set_device(shared_ptr
<devices::Device
>(
675 new devices::InputFile(
676 device_manager_
.context(),
677 file_name
.toStdString(),
680 set_device(shared_ptr
<devices::Device
>(
681 new devices::SessionFile(
682 device_manager_
.context(),
683 file_name
.toStdString())));
685 MainWindow::show_session_error(tr("Failed to load %1").arg(file_name
), e
.what());
686 set_default_device();
687 main_bar_
->update_device_list();
691 // Use the input file with .pvs extension if no setup file was given
692 if (setup_file_name
.isEmpty()) {
693 setup_file_name
= file_name
;
694 setup_file_name
.truncate(setup_file_name
.lastIndexOf('.'));
695 setup_file_name
.append(".pvs");
698 if (QFileInfo::exists(setup_file_name
) && QFileInfo(setup_file_name
).isReadable()) {
699 QSettings
settings_storage(setup_file_name
, QSettings::IniFormat
);
700 restore_setup(settings_storage
);
703 main_bar_
->update_device_list();
705 start_capture([&, errorMessage
](QString infoMessage
) {
706 MainWindow::show_session_error(errorMessage
, infoMessage
); });
708 set_name(QFileInfo(file_name
).fileName());
711 Session::capture_state
Session::get_capture_state() const
713 lock_guard
<mutex
> lock(sampling_mutex_
);
714 return capture_state_
;
717 void Session::start_capture(function
<void (const QString
)> error_handler
)
720 error_handler(tr("No active device set, can't start acquisition."));
726 // Check that at least one channel is enabled
727 const shared_ptr
<sigrok::Device
> sr_dev
= device_
->device();
729 const auto channels
= sr_dev
->channels();
730 if (!any_of(channels
.begin(), channels
.end(),
731 [](shared_ptr
<Channel
> channel
) {
732 return channel
->enabled(); })) {
733 error_handler(tr("No channels enabled."));
739 for (const shared_ptr
<data::SignalData
>& d
: all_signal_data_
)
742 trigger_list_
.clear();
744 // Revert name back to default name (e.g. "Session 1") for real devices
745 // as the (possibly saved) data is gone. File devices keep their name.
746 shared_ptr
<devices::HardwareDevice
> hw_device
=
747 dynamic_pointer_cast
< devices::HardwareDevice
>(device_
);
750 name_
= default_name_
;
755 sampling_thread_
= std::thread(
756 &Session::sample_thread_proc
, this, error_handler
);
759 void Session::stop_capture()
761 if (get_capture_state() != Stopped
)
764 // Check that sampling stopped
765 if (sampling_thread_
.joinable())
766 sampling_thread_
.join();
769 void Session::register_view(shared_ptr
<views::ViewBase
> view
)
774 views_
.push_back(view
);
776 // Add all device signals
779 // Add all other signals
780 vector
< shared_ptr
<data::SignalBase
> > view_signalbases
= view
->signalbases();
782 for (const shared_ptr
<data::SignalBase
>& signalbase
: signalbases_
) {
783 const int sb_exists
= count_if(
784 view_signalbases
.cbegin(), view_signalbases
.cend(),
785 [&](const shared_ptr
<data::SignalBase
> &sb
) {
786 return sb
== signalbase
;
789 // Add the signal to the view if it doesn't have it yet
791 switch (signalbase
->type()) {
792 case data::SignalBase::AnalogChannel
:
793 case data::SignalBase::LogicChannel
:
794 case data::SignalBase::MathChannel
:
795 view
->add_signalbase(signalbase
);
797 case data::SignalBase::DecodeChannel
:
799 view
->add_decode_signal(dynamic_pointer_cast
<data::DecodeSignal
>(signalbase
));
808 void Session::deregister_view(shared_ptr
<views::ViewBase
> view
)
810 views_
.erase(std::remove_if(views_
.begin(), views_
.end(),
811 [&](shared_ptr
<views::ViewBase
> v
) { return v
== view
; }),
814 if (views_
.empty()) {
817 // Without a view there can be no main bar
822 bool Session::has_view(shared_ptr
<views::ViewBase
> view
)
824 for (shared_ptr
<views::ViewBase
>& v
: views_
)
831 double Session::get_samplerate() const
833 double samplerate
= 0.0;
835 for (const shared_ptr
<pv::data::SignalData
>& d
: all_signal_data_
) {
837 const vector
< shared_ptr
<pv::data::Segment
> > segments
=
839 for (const shared_ptr
<pv::data::Segment
>& s
: segments
)
840 samplerate
= max(samplerate
, s
->samplerate());
842 // If there is no sample rate given we use samples as unit
843 if (samplerate
== 0.0)
849 uint32_t Session::get_segment_count() const
853 // Find the highest number of segments
854 for (const shared_ptr
<data::SignalData
>& data
: all_signal_data_
)
855 if (data
->get_segment_count() > value
)
856 value
= data
->get_segment_count();
861 vector
<util::Timestamp
> Session::get_triggers(uint32_t segment_id
) const
863 vector
<util::Timestamp
> result
;
865 for (const pair
<uint32_t, util::Timestamp
>& entry
: trigger_list_
)
866 if (entry
.first
== segment_id
)
867 result
.push_back(entry
.second
);
872 const vector
< shared_ptr
<data::SignalBase
> > Session::signalbases() const
877 void Session::add_generated_signal(shared_ptr
<data::SignalBase
> signal
)
879 signalbases_
.push_back(signal
);
881 for (shared_ptr
<views::ViewBase
>& view
: views_
)
882 view
->add_signalbase(signal
);
887 void Session::remove_generated_signal(shared_ptr
<data::SignalBase
> signal
)
892 signalbases_
.erase(std::remove_if(signalbases_
.begin(), signalbases_
.end(),
893 [&](shared_ptr
<data::SignalBase
> s
) { return s
== signal
; }),
896 for (shared_ptr
<views::ViewBase
>& view
: views_
)
897 view
->remove_signalbase(signal
);
903 shared_ptr
<data::DecodeSignal
> Session::add_decode_signal()
905 shared_ptr
<data::DecodeSignal
> signal
;
908 // Create the decode signal
909 signal
= make_shared
<data::DecodeSignal
>(*this);
911 signalbases_
.push_back(signal
);
913 // Add the decode signal to all views
914 for (shared_ptr
<views::ViewBase
>& view
: views_
)
915 view
->add_decode_signal(signal
);
916 } catch (runtime_error
& e
) {
917 remove_decode_signal(signal
);
926 void Session::remove_decode_signal(shared_ptr
<data::DecodeSignal
> signal
)
931 signalbases_
.erase(std::remove_if(signalbases_
.begin(), signalbases_
.end(),
932 [&](shared_ptr
<data::SignalBase
> s
) { return s
== signal
; }),
935 for (shared_ptr
<views::ViewBase
>& view
: views_
)
936 view
->remove_decode_signal(signal
);
942 bool Session::all_segments_complete(uint32_t segment_id
) const
944 bool all_complete
= true;
946 for (const shared_ptr
<data::SignalBase
>& base
: signalbases_
)
947 if (!base
->segment_is_complete(segment_id
))
948 all_complete
= false;
953 MetadataObjManager
* Session::metadata_obj_manager()
955 return &metadata_obj_manager_
;
958 void Session::set_capture_state(capture_state state
)
962 if (state
== Running
)
964 if (state
== Stopped
)
965 qDebug("Acquisition took %.2f s", acq_time_
.elapsed() / 1000.);
968 lock_guard
<mutex
> lock(sampling_mutex_
);
969 changed
= capture_state_
!= state
;
970 capture_state_
= state
;
974 capture_state_changed(state
);
977 void Session::update_signals()
980 signalbases_
.clear();
982 for (shared_ptr
<views::ViewBase
>& view
: views_
) {
983 view
->clear_signalbases();
985 view
->clear_decode_signals();
991 lock_guard
<recursive_mutex
> lock(data_mutex_
);
993 const shared_ptr
<sigrok::Device
> sr_dev
= device_
->device();
995 signalbases_
.clear();
997 for (shared_ptr
<views::ViewBase
>& view
: views_
) {
998 view
->clear_signalbases();
1000 view
->clear_decode_signals();
1006 // Detect what data types we will receive
1007 auto channels
= sr_dev
->channels();
1008 unsigned int logic_channel_count
= count_if(
1009 channels
.begin(), channels
.end(),
1010 [] (shared_ptr
<Channel
> channel
) {
1011 return channel
->type() == sigrok::ChannelType::LOGIC
; });
1013 // Create a common data container for the logic signalbases
1015 lock_guard
<recursive_mutex
> data_lock(data_mutex_
);
1017 if (logic_channel_count
== 0) {
1018 logic_data_
.reset();
1019 } else if (!logic_data_
||
1020 logic_data_
->num_channels() != logic_channel_count
) {
1021 logic_data_
.reset(new data::Logic(logic_channel_count
));
1022 assert(logic_data_
);
1026 // Create signalbases if necessary
1027 for (auto channel
: sr_dev
->channels()) {
1029 // Try to find the channel in the list of existing signalbases
1030 const auto iter
= find_if(signalbases_
.cbegin(), signalbases_
.cend(),
1031 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
->channel() == channel
; });
1033 // Not found, let's make a signalbase for it
1034 if (iter
== signalbases_
.cend()) {
1035 shared_ptr
<SignalBase
> signalbase
;
1036 switch(channel
->type()->id()) {
1037 case SR_CHANNEL_LOGIC
:
1038 signalbase
= make_shared
<data::SignalBase
>(channel
, data::SignalBase::LogicChannel
);
1039 signalbases_
.push_back(signalbase
);
1041 all_signal_data_
.insert(logic_data_
);
1042 signalbase
->set_data(logic_data_
);
1044 connect(this, SIGNAL(capture_state_changed(int)),
1045 signalbase
.get(), SLOT(on_capture_state_changed(int)));
1048 case SR_CHANNEL_ANALOG
:
1049 signalbase
= make_shared
<data::SignalBase
>(channel
, data::SignalBase::AnalogChannel
);
1050 signalbases_
.push_back(signalbase
);
1052 shared_ptr
<data::Analog
> data(new data::Analog());
1053 all_signal_data_
.insert(data
);
1054 signalbase
->set_data(data
);
1056 connect(this, SIGNAL(capture_state_changed(int)),
1057 signalbase
.get(), SLOT(on_capture_state_changed(int)));
1063 // Create and assign default signal groups if needed
1064 if (signal_groups_
.empty()) {
1065 for (auto& entry
: sr_dev
->channel_groups()) {
1066 const shared_ptr
<sigrok::ChannelGroup
>& group
= entry
.second
;
1068 if (group
->channels().size() <= 1)
1071 SignalGroup
* sg
= new SignalGroup(QString::fromStdString(entry
.first
));
1072 for (const shared_ptr
<sigrok::Channel
>& channel
: group
->channels()) {
1073 for (shared_ptr
<data::SignalBase
> s
: signalbases_
) {
1074 if (s
->channel() == channel
) {
1075 sg
->append_signal(s
);
1080 signal_groups_
.emplace_back(sg
);
1085 for (shared_ptr
<views::ViewBase
>& viewbase
: views_
) {
1086 vector
< shared_ptr
<SignalBase
> > view_signalbases
=
1087 viewbase
->signalbases();
1089 // Add all non-decode signalbases that don't yet exist in the view
1090 for (shared_ptr
<SignalBase
>& session_sb
: signalbases_
) {
1091 if (session_sb
->type() == SignalBase::DecodeChannel
)
1094 const auto iter
= find_if(view_signalbases
.cbegin(), view_signalbases
.cend(),
1095 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
== session_sb
; });
1097 if (iter
== view_signalbases
.cend())
1098 viewbase
->add_signalbase(session_sb
);
1101 // Remove all non-decode signalbases that no longer exist
1102 for (shared_ptr
<SignalBase
>& view_sb
: view_signalbases
) {
1103 if (view_sb
->type() == SignalBase::DecodeChannel
)
1106 const auto iter
= find_if(signalbases_
.cbegin(), signalbases_
.cend(),
1107 [&](const shared_ptr
<SignalBase
> &sb
) { return sb
== view_sb
; });
1109 if (iter
== signalbases_
.cend())
1110 viewbase
->remove_signalbase(view_sb
);
1117 shared_ptr
<data::SignalBase
> Session::signalbase_from_channel(
1118 shared_ptr
<sigrok::Channel
> channel
) const
1120 for (shared_ptr
<data::SignalBase
> sig
: signalbases_
) {
1122 if (sig
->channel() == channel
)
1125 return shared_ptr
<data::SignalBase
>();
1128 void Session::sample_thread_proc(function
<void (const QString
)> error_handler
)
1130 assert(error_handler
);
1133 pipeline_
= Pipeline::create();
1135 source_
= ElementFactory::create_element("filesrc", "source");
1136 sink_
= RefPtr
<AppSink
>::cast_dynamic(ElementFactory::create_element("appsink", "sink"));
1138 pipeline_
->add(source_
)->add(sink_
);
1139 source_
->link(sink_
);
1141 source_
->set_property("location", Glib::ustring("/tmp/dummy_binary"));
1143 sink_
->set_property("emit-signals", TRUE
);
1144 sink_
->signal_new_sample().connect(sigc::mem_fun(*this, &Session::on_gst_new_sample
));
1146 // Get the bus from the pipeline and add a bus watch to the default main context
1147 RefPtr
<Bus
> bus
= pipeline_
->get_bus();
1148 bus
->add_watch(sigc::mem_fun(this, &Session::on_gst_bus_message
));
1150 // Start pipeline and Wait until it finished processing
1151 pipeline_done_interrupt_
= false;
1152 pipeline_
->set_state(Gst::STATE_PLAYING
);
1154 unique_lock
<mutex
> pipeline_done_lock_(pipeline_done_mutex_
);
1155 pipeline_done_cond_
.wait(pipeline_done_lock_
);
1157 // Let the pipeline free all resources
1158 pipeline_
->set_state(Gst::STATE_NULL
);
1165 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1166 } catch (Error
& e
) {
1167 cur_samplerate_
= 0;
1170 out_of_memory_
= false;
1173 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1174 cur_logic_segment_
.reset();
1175 cur_analog_segments_
.clear();
1176 for (shared_ptr
<data::SignalBase
> sb
: signalbases_
)
1177 sb
->clear_sample_data();
1179 highest_segment_id_
= -1;
1180 frame_began_
= false;
1184 } catch (Error
& e
) {
1185 error_handler(e
.what());
1189 set_capture_state(device_
->session()->trigger() ?
1190 AwaitingTrigger
: Running
);
1194 } catch (Error
& e
) {
1195 error_handler(e
.what());
1196 set_capture_state(Stopped
);
1198 } catch (QString
& e
) {
1200 set_capture_state(Stopped
);
1204 set_capture_state(Stopped
);
1206 // Confirm that SR_DF_END was received
1207 if (cur_logic_segment_
)
1208 qDebug() << "WARNING: SR_DF_END was not received.";
1211 // Optimize memory usage
1212 free_unused_memory();
1214 // We now have unsaved data unless we just "captured" from a file
1215 shared_ptr
<devices::File
> file_device
=
1216 dynamic_pointer_cast
<devices::File
>(device_
);
1219 data_saved_
= false;
1222 error_handler(tr("Out of memory, acquisition stopped."));
1225 void Session::free_unused_memory()
1227 for (const shared_ptr
<data::SignalData
>& data
: all_signal_data_
) {
1228 const vector
< shared_ptr
<data::Segment
> > segments
= data
->segments();
1230 for (const shared_ptr
<data::Segment
>& segment
: segments
)
1231 segment
->free_unused_memory();
1235 void Session::signal_new_segment()
1237 int new_segment_id
= 0;
1239 if ((cur_logic_segment_
!= nullptr) || !cur_analog_segments_
.empty()) {
1241 // Determine new frame/segment number, assuming that all
1242 // signals have the same number of frames/segments
1243 if (cur_logic_segment_
) {
1244 new_segment_id
= logic_data_
->get_segment_count() - 1;
1246 shared_ptr
<sigrok::Channel
> any_channel
=
1247 (*cur_analog_segments_
.begin()).first
;
1249 shared_ptr
<data::SignalBase
> base
= signalbase_from_channel(any_channel
);
1252 shared_ptr
<data::Analog
> data(base
->analog_data());
1255 new_segment_id
= data
->get_segment_count() - 1;
1259 if (new_segment_id
> highest_segment_id_
) {
1260 highest_segment_id_
= new_segment_id
;
1261 new_segment(highest_segment_id_
);
1265 void Session::signal_segment_completed()
1269 for (const shared_ptr
<data::SignalBase
>& signalbase
: signalbases_
) {
1270 // We only care about analog and logic channels, not derived ones
1271 if (signalbase
->type() == data::SignalBase::AnalogChannel
) {
1272 segment_id
= signalbase
->analog_data()->get_segment_count() - 1;
1276 if (signalbase
->type() == data::SignalBase::LogicChannel
) {
1277 segment_id
= signalbase
->logic_data()->get_segment_count() - 1;
1282 if (segment_id
>= 0)
1283 segment_completed(segment_id
);
1287 bool Session::on_gst_bus_message(const Glib::RefPtr
<Gst::Bus
>& bus
, const Glib::RefPtr
<Gst::Message
>& message
)
1291 if ((message
->get_source() == pipeline_
) && \
1292 ((message
->get_message_type() == Gst::MESSAGE_EOS
)))
1293 pipeline_done_cond_
.notify_one();
1295 // TODO Also evaluate MESSAGE_STREAM_STATUS to receive error notifications
1300 Gst::FlowReturn
Session::on_gst_new_sample()
1302 RefPtr
<Gst::Sample
> sample
= sink_
->pull_sample();
1303 RefPtr
<Gst::Buffer
> buf
= sample
->get_buffer();
1305 for (uint32_t block_id
= 0; block_id
< buf
->n_memory(); block_id
++) {
1306 RefPtr
<Gst::Memory
> buf_mem
= buf
->get_memory(block_id
);
1307 Gst::MapInfo mapinfo
;
1308 buf_mem
->map(mapinfo
, Gst::MAP_READ
);
1310 shared_ptr
<sigrok::Packet
> logic_packet
=
1311 sr_context
->create_logic_packet(mapinfo
.get_data(), buf
->get_size(), 1);
1314 feed_in_logic(dynamic_pointer_cast
<sigrok::Logic
>(logic_packet
->payload()));
1315 } catch (bad_alloc
&) {
1316 out_of_memory_
= true;
1318 buf_mem
->unmap(mapinfo
);
1319 return Gst::FLOW_ERROR
;
1322 buf_mem
->unmap(mapinfo
);
1325 return Gst::FLOW_OK
;
1329 void Session::feed_in_header()
1331 // Nothing to do here for now
1334 void Session::feed_in_meta(shared_ptr
<Meta
> meta
)
1336 for (auto& entry
: meta
->config()) {
1337 switch (entry
.first
->id()) {
1338 case SR_CONF_SAMPLERATE
:
1339 cur_samplerate_
= g_variant_get_uint64(entry
.second
.gobj());
1342 qDebug() << "Received meta data key" << entry
.first
->id() << ", ignoring.";
1350 void Session::feed_in_trigger()
1352 // The channel containing most samples should be most accurate
1353 uint64_t sample_count
= 0;
1356 for (const shared_ptr
<pv::data::SignalData
>& d
: all_signal_data_
) {
1358 uint64_t temp_count
= 0;
1360 const vector
< shared_ptr
<pv::data::Segment
> > segments
=
1362 for (const shared_ptr
<pv::data::Segment
> &s
: segments
)
1363 temp_count
+= s
->get_sample_count();
1365 if (temp_count
> sample_count
)
1366 sample_count
= temp_count
;
1370 uint32_t segment_id
= 0; // Default segment when no frames are used
1372 // If a frame began, we'd ideally be able to use the highest segment ID for
1373 // the trigger. However, as new segments are only created when logic or
1374 // analog data comes in, this doesn't work if the trigger appears right
1375 // after the beginning of the frame, before any sample data.
1376 // For this reason, we use highest segment ID + 1 if no sample data came in
1377 // yet and the highest segment ID otherwise.
1379 segment_id
= highest_segment_id_
;
1380 if (!cur_logic_segment_
&& (cur_analog_segments_
.size() == 0))
1384 // TODO Create timestamp from segment start time + segment's current sample count
1385 util::Timestamp timestamp
= sample_count
/ get_samplerate();
1386 trigger_list_
.emplace_back(segment_id
, timestamp
);
1387 trigger_event(segment_id
, timestamp
);
1390 void Session::feed_in_frame_begin()
1392 frame_began_
= true;
1395 void Session::feed_in_frame_end()
1401 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1403 if (cur_logic_segment_
)
1404 cur_logic_segment_
->set_complete();
1406 for (auto& entry
: cur_analog_segments_
) {
1407 shared_ptr
<data::AnalogSegment
> segment
= entry
.second
;
1408 segment
->set_complete();
1411 cur_logic_segment_
.reset();
1412 cur_analog_segments_
.clear();
1415 frame_began_
= false;
1417 signal_segment_completed();
1420 void Session::feed_in_logic(shared_ptr
<sigrok::Logic
> logic
)
1422 if (logic
->data_length() == 0) {
1423 qDebug() << "WARNING: Received logic packet with 0 samples.";
1427 if (logic
->unit_size() > 8)
1428 throw QString(tr("Can't handle more than 64 logic channels."));
1430 if (!cur_samplerate_
)
1432 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1433 } catch (Error
& e
) {
1437 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1440 // The only reason logic_data_ would not have been created is
1441 // if it was not possible to determine the signals when the
1442 // device was created.
1446 if (!cur_logic_segment_
) {
1447 // This could be the first packet after a trigger
1448 set_capture_state(Running
);
1450 // Create a new data segment
1451 cur_logic_segment_
= make_shared
<data::LogicSegment
>(
1452 *logic_data_
, logic_data_
->get_segment_count(),
1453 logic
->unit_size(), cur_samplerate_
);
1454 logic_data_
->push_segment(cur_logic_segment_
);
1456 signal_new_segment();
1459 cur_logic_segment_
->append_payload(logic
);
1464 void Session::feed_in_analog(shared_ptr
<sigrok::Analog
> analog
)
1466 if (analog
->num_samples() == 0) {
1467 qDebug() << "WARNING: Received analog packet with 0 samples.";
1471 if (!cur_samplerate_
)
1473 cur_samplerate_
= device_
->read_config
<uint64_t>(ConfigKey::SAMPLERATE
);
1474 } catch (Error
& e
) {
1478 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1480 const vector
<shared_ptr
<Channel
>> channels
= analog
->channels();
1481 bool sweep_beginning
= false;
1483 unique_ptr
<float[]> data(new float[analog
->num_samples() * channels
.size()]);
1484 analog
->get_data_as_float(data
.get());
1486 if (signalbases_
.empty())
1489 float *channel_data
= data
.get();
1490 for (auto& channel
: channels
) {
1491 shared_ptr
<data::AnalogSegment
> segment
;
1493 // Try to get the segment of the channel
1494 const map
< shared_ptr
<Channel
>, shared_ptr
<data::AnalogSegment
> >::
1495 iterator iter
= cur_analog_segments_
.find(channel
);
1496 if (iter
!= cur_analog_segments_
.end())
1497 segment
= (*iter
).second
;
1499 // If no segment was found, this means we haven't
1500 // created one yet. i.e. this is the first packet
1501 // in the sweep containing this segment.
1502 sweep_beginning
= true;
1504 // Find the analog data associated with the channel
1505 shared_ptr
<data::SignalBase
> base
= signalbase_from_channel(channel
);
1508 shared_ptr
<data::Analog
> data(base
->analog_data());
1511 // Create a segment, keep it in the maps of channels
1512 segment
= make_shared
<data::AnalogSegment
>(
1513 *data
, data
->get_segment_count(), cur_samplerate_
);
1514 cur_analog_segments_
[channel
] = segment
;
1516 // Push the segment into the analog data.
1517 data
->push_segment(segment
);
1519 signal_new_segment();
1524 // Append the samples in the segment
1525 segment
->append_interleaved_samples(channel_data
++, analog
->num_samples(),
1529 if (sweep_beginning
) {
1530 // This could be the first packet after a trigger
1531 set_capture_state(Running
);
1537 void Session::data_feed_in(shared_ptr
<sigrok::Device
> device
,
1538 shared_ptr
<Packet
> packet
)
1543 assert(device
== device_
->device());
1546 switch (packet
->type()->id()) {
1552 feed_in_meta(dynamic_pointer_cast
<Meta
>(packet
->payload()));
1561 feed_in_logic(dynamic_pointer_cast
<Logic
>(packet
->payload()));
1562 } catch (bad_alloc
&) {
1563 out_of_memory_
= true;
1570 feed_in_analog(dynamic_pointer_cast
<Analog
>(packet
->payload()));
1571 } catch (bad_alloc
&) {
1572 out_of_memory_
= true;
1577 case SR_DF_FRAME_BEGIN
:
1578 feed_in_frame_begin();
1581 case SR_DF_FRAME_END
:
1582 feed_in_frame_end();
1586 // Strictly speaking, this is performed when a frame end marker was
1587 // received, so there's no point doing this again. However, not all
1588 // devices use frames, and for those devices, we need to do it here.
1590 lock_guard
<recursive_mutex
> lock(data_mutex_
);
1592 if (cur_logic_segment_
)
1593 cur_logic_segment_
->set_complete();
1595 for (auto& entry
: cur_analog_segments_
) {
1596 shared_ptr
<data::AnalogSegment
> segment
= entry
.second
;
1597 segment
->set_complete();
1600 cur_logic_segment_
.reset();
1601 cur_analog_segments_
.clear();
1610 void Session::on_data_saved()
1615 #ifdef ENABLE_DECODE
1616 void Session::on_new_decoders_selected(vector
<const srd_decoder
*> decoders
)
1618 assert(decoders
.size() > 0);
1620 shared_ptr
<data::DecodeSignal
> signal
= add_decode_signal();
1623 for (unsigned int i
= 0; i
< decoders
.size(); i
++) {
1624 const srd_decoder
* d
= decoders
[i
];
1625 signal
->stack_decoder(d
, !(i
< decoders
.size() - 1));