]> sigrok.org Git - pulseview.git/blame - pv/session.cpp
About: Also list glibmm/boost/libsigrokdecode version details.
[pulseview.git] / pv / session.cpp
CommitLineData
2953961c 1/*
b3f22de0 2 * This file is part of the PulseView project.
2953961c 3 *
1bc6525b 4 * Copyright (C) 2012-14 Joel Holdsworth <joel@airwebreathe.org.uk>
2953961c
JH
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
efdec55a 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
2953961c
JH
18 */
19
43017494
SA
20#include <QFileInfo>
21
1e4d7c4d
SA
22#include <cassert>
23#include <mutex>
24#include <stdexcept>
4e5a4405 25
1e4d7c4d 26#include <sys/stat.h>
2953961c 27
2acdb232 28#include "devicemanager.hpp"
aca9aa83 29#include "session.hpp"
119aff65 30
2acdb232 31#include "data/analog.hpp"
f3d66e52 32#include "data/analogsegment.hpp"
aca9aa83 33#include "data/decode/decoder.hpp"
2acdb232
JH
34#include "data/decoderstack.hpp"
35#include "data/logic.hpp"
f3d66e52 36#include "data/logicsegment.hpp"
bf0edd2b 37#include "data/signalbase.hpp"
82c7f640 38
da30ecb7 39#include "devices/hardwaredevice.hpp"
fd22c71c 40#include "devices/inputfile.hpp"
da30ecb7
JH
41#include "devices/sessionfile.hpp"
42
0f8f8c18
SA
43#include "toolbars/mainbar.hpp"
44
2acdb232
JH
45#include "view/analogsignal.hpp"
46#include "view/decodetrace.hpp"
47#include "view/logicsignal.hpp"
47e9e7bb
SA
48#include "view/signal.hpp"
49#include "view/view.hpp"
28a4c9c5 50
fe3a1c21 51#include <libsigrokcxx/libsigrokcxx.hpp>
e8d00928 52
1e4d7c4d
SA
53#ifdef ENABLE_DECODE
54#include <libsigrokdecode/libsigrokdecode.h>
55#endif
56
6f925ba9 57using std::bad_alloc;
f9abf97e 58using std::dynamic_pointer_cast;
6f925ba9 59using std::find_if;
d2344534 60using std::function;
3b68d03d 61using std::lock_guard;
d873f4d6 62using std::list;
6f925ba9
UH
63using std::make_pair;
64using std::make_shared;
819f4c25 65using std::map;
6f925ba9
UH
66using std::max;
67using std::move;
aca64cac 68using std::mutex;
fd22c71c 69using std::pair;
8524a597 70using std::recursive_mutex;
6f925ba9 71using std::runtime_error;
f9abf97e 72using std::shared_ptr;
819f4c25 73using std::string;
78b0af3e 74using std::unordered_set;
819f4c25 75using std::vector;
28a4c9c5 76
e8d00928
ML
77using sigrok::Analog;
78using sigrok::Channel;
e8d00928
ML
79using sigrok::ConfigKey;
80using sigrok::DatafeedCallbackFunction;
e8d00928 81using sigrok::Error;
fd22c71c 82using sigrok::InputFormat;
e8d00928
ML
83using sigrok::Logic;
84using sigrok::Meta;
85using sigrok::Packet;
e8d00928 86using sigrok::Session;
e8d00928
ML
87
88using Glib::VariantBase;
51e77110 89
e8d00928 90namespace pv {
101e7a9b 91Session::Session(DeviceManager &device_manager, QString name) :
8dbbc7f0 92 device_manager_(device_manager),
33e1afbe 93 default_name_(name),
101e7a9b 94 name_(name),
ff008de6 95 capture_state_(Stopped),
5ccfc97e
SA
96 cur_samplerate_(0),
97 data_saved_(true)
2953961c 98{
2953961c
JH
99}
100
2b81ae46 101Session::~Session()
2953961c 102{
04463625 103 // Stop and join to the thread
5b7cf66c 104 stop_capture();
2953961c
JH
105}
106
2b81ae46 107DeviceManager& Session::device_manager()
4cb0b033 108{
8dbbc7f0 109 return device_manager_;
4cb0b033
JH
110}
111
2b81ae46 112const DeviceManager& Session::device_manager() const
4cb0b033 113{
8dbbc7f0 114 return device_manager_;
4cb0b033
JH
115}
116
da30ecb7 117shared_ptr<sigrok::Session> Session::session() const
1f4caa77 118{
da30ecb7
JH
119 if (!device_)
120 return shared_ptr<sigrok::Session>();
121 return device_->session();
1f4caa77
JH
122}
123
da30ecb7 124shared_ptr<devices::Device> Session::device() const
dc0867ff 125{
8dbbc7f0 126 return device_;
dc0867ff
JH
127}
128
101e7a9b
SA
129QString Session::name() const
130{
131 return name_;
132}
133
134void Session::set_name(QString name)
135{
136 if (default_name_.isEmpty())
137 default_name_ = name;
138
139 name_ = name;
140
141 name_changed();
142}
143
6f925ba9 144const list< shared_ptr<views::ViewBase> > Session::views() const
36a8185e
SA
145{
146 return views_;
147}
148
6f925ba9 149shared_ptr<views::ViewBase> Session::main_view() const
0f8f8c18
SA
150{
151 return main_view_;
152}
153
6f925ba9 154void Session::set_main_bar(shared_ptr<pv::toolbars::MainBar> main_bar)
0f8f8c18
SA
155{
156 main_bar_ = main_bar;
157}
158
159shared_ptr<pv::toolbars::MainBar> Session::main_bar() const
160{
161 return main_bar_;
162}
163
5ccfc97e
SA
164bool Session::data_saved() const
165{
166 return data_saved_;
167}
168
101e7a9b
SA
169void Session::save_settings(QSettings &settings) const
170{
171 map<string, string> dev_info;
172 list<string> key_list;
3a21afa6 173 int stacks = 0, views = 0;
101e7a9b
SA
174
175 if (device_) {
43017494
SA
176 shared_ptr<devices::HardwareDevice> hw_device =
177 dynamic_pointer_cast< devices::HardwareDevice >(device_);
178
179 if (hw_device) {
180 settings.setValue("device_type", "hardware");
181 settings.beginGroup("device");
182
326cf6fe
UH
183 key_list.emplace_back("vendor");
184 key_list.emplace_back("model");
185 key_list.emplace_back("version");
186 key_list.emplace_back("serial_num");
187 key_list.emplace_back("connection_id");
43017494
SA
188
189 dev_info = device_manager_.get_device_info(device_);
190
191 for (string key : key_list) {
192 if (dev_info.count(key))
193 settings.setValue(QString::fromUtf8(key.c_str()),
194 QString::fromUtf8(dev_info.at(key).c_str()));
195 else
196 settings.remove(QString::fromUtf8(key.c_str()));
197 }
101e7a9b 198
43017494
SA
199 settings.endGroup();
200 }
101e7a9b 201
43017494
SA
202 shared_ptr<devices::SessionFile> sessionfile_device =
203 dynamic_pointer_cast< devices::SessionFile >(device_);
204
205 if (sessionfile_device) {
206 settings.setValue("device_type", "sessionfile");
207 settings.beginGroup("device");
208 settings.setValue("filename", QString::fromStdString(
209 sessionfile_device->full_name()));
210 settings.endGroup();
101e7a9b
SA
211 }
212
aecae05c
SA
213 // Save channels and decoders
214 for (shared_ptr<data::SignalBase> base : signalbases_) {
215#ifdef ENABLE_DECODE
216 if (base->is_decode_signal()) {
217 shared_ptr<pv::data::DecoderStack> decoder_stack =
218 base->decoder_stack();
6f925ba9 219 shared_ptr<data::decode::Decoder> top_decoder =
aecae05c
SA
220 decoder_stack->stack().front();
221
222 settings.beginGroup("decoder_stack" + QString::number(stacks++));
223 settings.setValue("id", top_decoder->decoder()->id);
224 settings.setValue("name", top_decoder->decoder()->name);
225 settings.endGroup();
226 } else
227#endif
228 {
229 settings.beginGroup(base->internal_name());
6de38b17 230 base->save_settings(settings);
aecae05c
SA
231 settings.endGroup();
232 }
233 }
101e7a9b 234
aecae05c 235 settings.setValue("decoder_stacks", stacks);
3a21afa6
SA
236
237 // Save view states and their signal settings
238 // Note: main_view must be saved as view0
239 settings.beginGroup("view" + QString::number(views++));
240 main_view_->save_settings(settings);
241 settings.endGroup();
242
f4e57597 243 for (shared_ptr<views::ViewBase> view : views_) {
3a21afa6
SA
244 if (view != main_view_) {
245 settings.beginGroup("view" + QString::number(views++));
246 view->save_settings(settings);
247 settings.endGroup();
248 }
249 }
250
251 settings.setValue("views", views);
101e7a9b
SA
252 }
253}
254
255void Session::restore_settings(QSettings &settings)
256{
43017494
SA
257 shared_ptr<devices::Device> device;
258
259 QString device_type = settings.value("device_type").toString();
260
261 if (device_type == "hardware") {
262 map<string, string> dev_info;
263 list<string> key_list;
264
265 // Re-select last used device if possible but only if it's not demo
266 settings.beginGroup("device");
326cf6fe
UH
267 key_list.emplace_back("vendor");
268 key_list.emplace_back("model");
269 key_list.emplace_back("version");
270 key_list.emplace_back("serial_num");
271 key_list.emplace_back("connection_id");
43017494
SA
272
273 for (string key : key_list) {
274 const QString k = QString::fromStdString(key);
275 if (!settings.contains(k))
276 continue;
277
278 const string value = settings.value(k).toString().toStdString();
279 if (!value.empty())
6f925ba9 280 dev_info.insert(make_pair(key, value));
43017494
SA
281 }
282
283 if (dev_info.count("model") > 0)
284 device = device_manager_.find_device_from_info(dev_info);
285
286 if (device)
287 set_device(device);
288
289 settings.endGroup();
101e7a9b
SA
290 }
291
43017494
SA
292 if (device_type == "sessionfile") {
293 settings.beginGroup("device");
294 QString filename = settings.value("filename").toString();
295 settings.endGroup();
101e7a9b 296
43017494 297 if (QFileInfo(filename).isReadable()) {
067bb624 298 device = make_shared<devices::SessionFile>(device_manager_.context(),
43017494
SA
299 filename.toStdString());
300 set_device(device);
101e7a9b 301
43017494
SA
302 // TODO Perform error handling
303 start_capture([](QString infoMessage) { (void)infoMessage; });
33e1afbe
SA
304
305 set_name(QFileInfo(filename).fileName());
43017494
SA
306 }
307 }
308
309 if (device) {
aecae05c
SA
310 // Restore channels
311 for (shared_ptr<data::SignalBase> base : signalbases_) {
312 settings.beginGroup(base->internal_name());
6de38b17 313 base->restore_settings(settings);
aecae05c
SA
314 settings.endGroup();
315 }
316
317 // Restore decoders
318#ifdef ENABLE_DECODE
319 int stacks = settings.value("decoder_stacks").toInt();
320
321 for (int i = 0; i < stacks; i++) {
322 settings.beginGroup("decoder_stack" + QString::number(i++));
323
324 QString id = settings.value("id").toString();
325 add_decoder(srd_decoder_get_by_id(id.toStdString().c_str()));
326
327 settings.endGroup();
328 }
329#endif
3a21afa6
SA
330
331 // Restore views
332 int views = settings.value("views").toInt();
333
334 for (int i = 0; i < views; i++) {
335 settings.beginGroup("view" + QString::number(i));
336
337 if (i > 0) {
f4e57597 338 views::ViewType type = (views::ViewType)settings.value("type").toInt();
3a21afa6
SA
339 add_view(name_, type, this);
340 views_.back()->restore_settings(settings);
341 } else
342 main_view_->restore_settings(settings);
343
344 settings.endGroup();
345 }
101e7a9b 346 }
101e7a9b
SA
347}
348
fd22c71c
SA
349void Session::select_device(shared_ptr<devices::Device> device)
350{
351 try {
352 if (device)
353 set_device(device);
354 else
355 set_default_device();
356 } catch (const QString &e) {
357 main_bar_->session_error(tr("Failed to Select Device"),
358 tr("Failed to Select Device"));
359 }
360}
361
da30ecb7 362void Session::set_device(shared_ptr<devices::Device> device)
d64d1596 363{
da30ecb7
JH
364 assert(device);
365
82596f46
JH
366 // Ensure we are not capturing before setting the device
367 stop_capture();
368
4d6c6ea3
SA
369 if (device_)
370 device_->close();
371
86123e2e
SA
372 device_.reset();
373
7b254679 374 // Revert name back to default name (e.g. "Session 1") as the data is gone
101e7a9b
SA
375 name_ = default_name_;
376 name_changed();
377
cc9a7898 378 // Remove all stored data
6f925ba9 379 for (shared_ptr<views::ViewBase> view : views_) {
47e9e7bb 380 view->clear_signals();
bb7dd726 381#ifdef ENABLE_DECODE
f4e57597 382 view->clear_decode_signals();
bb7dd726
SA
383#endif
384 }
47e9e7bb
SA
385 for (const shared_ptr<data::SignalData> d : all_signal_data_)
386 d->clear();
cc9a7898 387 all_signal_data_.clear();
47e9e7bb 388 signalbases_.clear();
4b0d7046
SA
389 cur_logic_segment_.reset();
390
391 for (auto entry : cur_analog_segments_) {
392 shared_ptr<sigrok::Channel>(entry.first).reset();
393 shared_ptr<data::AnalogSegment>(entry.second).reset();
394 }
395
396 logic_data_.reset();
4b0d7046 397
86123e2e
SA
398 signals_changed();
399
6f925ba9 400 device_ = move(device);
7e0c99bf
SA
401
402 try {
403 device_->open();
404 } catch (const QString &e) {
405 device_.reset();
7e0c99bf
SA
406 }
407
bcd64b9b
SA
408 if (device_) {
409 device_->session()->add_datafeed_callback([=]
410 (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
411 data_feed_in(device, packet);
412 });
413
414 update_signals();
415 }
ae2d1bc5 416
91f8fe8c 417 device_changed();
ae2d1bc5 418}
85843b14 419
2b81ae46 420void Session::set_default_device()
6fd0b639 421{
da30ecb7 422 const list< shared_ptr<devices::HardwareDevice> > &devices =
8dbbc7f0 423 device_manager_.devices();
6fd0b639 424
da30ecb7
JH
425 if (devices.empty())
426 return;
dc0867ff 427
da30ecb7 428 // Try and find the demo device and select that by default
6f925ba9 429 const auto iter = find_if(devices.begin(), devices.end(),
da30ecb7 430 [] (const shared_ptr<devices::HardwareDevice> &d) {
6f925ba9 431 return d->hardware_device()->driver()->name() == "demo"; });
da30ecb7 432 set_device((iter == devices.end()) ? devices.front() : *iter);
dc0867ff
JH
433}
434
6f925ba9 435void Session::load_init_file(const string &file_name, const string &format)
fd22c71c
SA
436{
437 shared_ptr<InputFormat> input_format;
438
439 if (!format.empty()) {
440 const map<string, shared_ptr<InputFormat> > formats =
441 device_manager_.context()->input_formats();
442 const auto iter = find_if(formats.begin(), formats.end(),
443 [&](const pair<string, shared_ptr<InputFormat> > f) {
444 return f.first == format; });
445 if (iter == formats.end()) {
446 main_bar_->session_error(tr("Error"),
447 tr("Unexpected input format: %s").arg(QString::fromStdString(format)));
448 return;
449 }
450
451 input_format = (*iter).second;
452 }
453
454 load_file(QString::fromStdString(file_name), input_format);
455}
456
457void Session::load_file(QString file_name,
6f925ba9
UH
458 shared_ptr<sigrok::InputFormat> format,
459 const map<string, Glib::VariantBase> &options)
fd22c71c
SA
460{
461 const QString errorMessage(
462 QString("Failed to load file %1").arg(file_name));
463
464 try {
465 if (format)
466 set_device(shared_ptr<devices::Device>(
467 new devices::InputFile(
468 device_manager_.context(),
469 file_name.toStdString(),
470 format, options)));
471 else
472 set_device(shared_ptr<devices::Device>(
473 new devices::SessionFile(
474 device_manager_.context(),
475 file_name.toStdString())));
476 } catch (Error e) {
477 main_bar_->session_error(tr("Failed to load ") + file_name, e.what());
478 set_default_device();
479 main_bar_->update_device_list();
480 return;
481 }
482
483 main_bar_->update_device_list();
484
485 start_capture([&, errorMessage](QString infoMessage) {
486 main_bar_->session_error(errorMessage, infoMessage); });
487
488 set_name(QFileInfo(file_name).fileName());
489}
490
2b81ae46 491Session::capture_state Session::get_capture_state() const
5b7cf66c 492{
8dbbc7f0
JH
493 lock_guard<mutex> lock(sampling_mutex_);
494 return capture_state_;
5b7cf66c
JH
495}
496
2b81ae46 497void Session::start_capture(function<void (const QString)> error_handler)
2e2946fe 498{
34c11fa7
SA
499 if (!device_) {
500 error_handler(tr("No active device set, can't start acquisition."));
501 return;
502 }
503
5b7cf66c
JH
504 stop_capture();
505
6ac6242b 506 // Check that at least one channel is enabled
e6c1382e
JH
507 const shared_ptr<sigrok::Device> sr_dev = device_->device();
508 if (sr_dev) {
509 const auto channels = sr_dev->channels();
6f925ba9 510 if (!any_of(channels.begin(), channels.end(),
e6c1382e
JH
511 [](shared_ptr<Channel> channel) {
512 return channel->enabled(); })) {
513 error_handler(tr("No channels enabled."));
514 return;
515 }
9c48fa57
JH
516 }
517
53ea4c6c 518 // Clear signal data
47e9e7bb
SA
519 for (const shared_ptr<data::SignalData> d : all_signal_data_)
520 d->clear();
53ea4c6c 521
53bb2e1d
SA
522 // Revert name back to default name (e.g. "Session 1") for real devices
523 // as the (possibly saved) data is gone. File devices keep their name.
524 shared_ptr<devices::HardwareDevice> hw_device =
525 dynamic_pointer_cast< devices::HardwareDevice >(device_);
526
527 if (hw_device) {
528 name_ = default_name_;
529 name_changed();
530 }
101e7a9b 531
9c48fa57 532 // Begin the session
8dbbc7f0 533 sampling_thread_ = std::thread(
2b05d311 534 &Session::sample_thread_proc, this, error_handler);
2e2946fe
JH
535}
536
2b81ae46 537void Session::stop_capture()
5b7cf66c 538{
04463625 539 if (get_capture_state() != Stopped)
da30ecb7 540 device_->stop();
5b7cf66c
JH
541
542 // Check that sampling stopped
8dbbc7f0
JH
543 if (sampling_thread_.joinable())
544 sampling_thread_.join();
5b7cf66c
JH
545}
546
6f925ba9 547void Session::register_view(shared_ptr<views::ViewBase> view)
47e9e7bb 548{
0f8f8c18
SA
549 if (views_.empty()) {
550 main_view_ = view;
551 }
552
3a21afa6 553 views_.push_back(view);
53e8927d
SA
554
555 update_signals();
47e9e7bb
SA
556}
557
6f925ba9 558void Session::deregister_view(shared_ptr<views::ViewBase> view)
47e9e7bb 559{
6f925ba9 560 views_.remove_if([&](shared_ptr<views::ViewBase> v) { return v == view; });
0f8f8c18
SA
561
562 if (views_.empty()) {
563 main_view_.reset();
564
565 // Without a view there can be no main bar
566 main_bar_.reset();
567 }
47e9e7bb
SA
568}
569
6f925ba9 570bool Session::has_view(shared_ptr<views::ViewBase> view)
101e7a9b 571{
6f925ba9 572 for (shared_ptr<views::ViewBase> v : views_)
3a21afa6
SA
573 if (v == view)
574 return true;
575
576 return false;
101e7a9b
SA
577}
578
2220e942
SA
579double Session::get_samplerate() const
580{
581 double samplerate = 0.0;
582
47e9e7bb
SA
583 for (const shared_ptr<pv::data::SignalData> d : all_signal_data_) {
584 assert(d);
585 const vector< shared_ptr<pv::data::Segment> > segments =
586 d->segments();
587 for (const shared_ptr<pv::data::Segment> &s : segments)
6f925ba9 588 samplerate = max(samplerate, s->samplerate());
2220e942 589 }
2220e942
SA
590 // If there is no sample rate given we use samples as unit
591 if (samplerate == 0.0)
592 samplerate = 1.0;
593
594 return samplerate;
595}
596
6f925ba9 597const unordered_set< shared_ptr<data::SignalBase> > Session::signalbases() const
2e2946fe 598{
47e9e7bb 599 return signalbases_;
2e2946fe
JH
600}
601
269528f5 602#ifdef ENABLE_DECODE
2b81ae46 603bool Session::add_decoder(srd_decoder *const dec)
82c7f640 604{
a7336fb2
SA
605 if (!dec)
606 return false;
607
04394ded 608 map<const srd_channel*, shared_ptr<data::SignalBase> > channels;
7491a29f 609 shared_ptr<data::DecoderStack> decoder_stack;
4e5a4405 610
2ad82c2e 611 try {
4e5a4405 612 // Create the decoder
067bb624 613 decoder_stack = make_shared<data::DecoderStack>(*this, dec);
4e5a4405 614
6ac6242b 615 // Make a list of all the channels
6f925ba9 616 vector<const srd_channel*> all_channels;
f3290553 617 for (const GSList *i = dec->channels; i; i = i->next)
6ac6242b 618 all_channels.push_back((const srd_channel*)i->data);
f3290553 619 for (const GSList *i = dec->opt_channels; i; i = i->next)
6ac6242b 620 all_channels.push_back((const srd_channel*)i->data);
d2f46d27 621
6ac6242b
ML
622 // Auto select the initial channels
623 for (const srd_channel *pdch : all_channels)
04394ded 624 for (shared_ptr<data::SignalBase> b : signalbases_) {
79c4a9c8 625 if (b->logic_data()) {
04394ded
SA
626 if (QString::fromUtf8(pdch->name).toLower().
627 contains(b->name().toLower()))
628 channels[pdch] = b;
629 }
4e5a4405 630 }
4e5a4405 631
7491a29f
JH
632 assert(decoder_stack);
633 assert(!decoder_stack->stack().empty());
634 assert(decoder_stack->stack().front());
6ac6242b 635 decoder_stack->stack().front()->set_channels(channels);
4e5a4405
JH
636
637 // Create the decode signal
bf0edd2b 638 shared_ptr<data::SignalBase> signalbase =
472a80c5 639 make_shared<data::SignalBase>(nullptr, data::SignalBase::DecodeChannel);
bf0edd2b 640
bb7dd726 641 signalbase->set_decoder_stack(decoder_stack);
aecae05c 642 signalbases_.insert(signalbase);
bb7dd726 643
6f925ba9 644 for (shared_ptr<views::ViewBase> view : views_)
f4e57597 645 view->add_decode_signal(signalbase);
6f925ba9 646 } catch (runtime_error e) {
e92cd4e4
JH
647 return false;
648 }
649
82c7f640 650 signals_changed();
e92cd4e4 651
7491a29f
JH
652 // Do an initial decode
653 decoder_stack->begin_decode();
654
e92cd4e4 655 return true;
82c7f640
JH
656}
657
bb7dd726 658void Session::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
38eeddea 659{
2d25fc47
SA
660 signalbases_.erase(signalbase);
661
6f925ba9 662 for (shared_ptr<views::ViewBase> view : views_)
f4e57597 663 view->remove_decode_signal(signalbase);
2d25fc47
SA
664
665 signals_changed();
c51482b3 666}
269528f5 667#endif
c51482b3 668
2b81ae46 669void Session::set_capture_state(capture_state state)
6ac96c2e 670{
896936e5
TS
671 bool changed;
672
673 {
674 lock_guard<mutex> lock(sampling_mutex_);
675 changed = capture_state_ != state;
676 capture_state_ = state;
677 }
678
f3290553 679 if (changed)
2b49eeb0 680 capture_state_changed(state);
6ac96c2e
JH
681}
682
ffe00119 683void Session::update_signals()
b087ba7f 684{
076eefa4 685 if (!device_) {
47e9e7bb 686 signalbases_.clear();
076eefa4 687 logic_data_.reset();
6f925ba9 688 for (shared_ptr<views::ViewBase> view : views_) {
47e9e7bb 689 view->clear_signals();
bb7dd726 690#ifdef ENABLE_DECODE
f4e57597 691 view->clear_decode_signals();
bb7dd726
SA
692#endif
693 }
076eefa4
SA
694 return;
695 }
e6c1382e
JH
696
697 lock_guard<recursive_mutex> lock(data_mutex_);
b087ba7f 698
ffe00119 699 const shared_ptr<sigrok::Device> sr_dev = device_->device();
c6412b47 700 if (!sr_dev) {
47e9e7bb 701 signalbases_.clear();
c6412b47 702 logic_data_.reset();
6f925ba9 703 for (shared_ptr<views::ViewBase> view : views_) {
47e9e7bb 704 view->clear_signals();
bb7dd726 705#ifdef ENABLE_DECODE
f4e57597 706 view->clear_decode_signals();
bb7dd726
SA
707#endif
708 }
c6412b47
JH
709 return;
710 }
711
b087ba7f 712 // Detect what data types we will receive
c6412b47 713 auto channels = sr_dev->channels();
6f925ba9 714 unsigned int logic_channel_count = count_if(
e8d00928
ML
715 channels.begin(), channels.end(),
716 [] (shared_ptr<Channel> channel) {
472a80c5 717 return channel->type() == sigrok::ChannelType::LOGIC; });
b087ba7f 718
f3d66e52 719 // Create data containers for the logic data segments
b087ba7f 720 {
8524a597 721 lock_guard<recursive_mutex> data_lock(data_mutex_);
b087ba7f 722
3917ba77
JH
723 if (logic_channel_count == 0) {
724 logic_data_.reset();
725 } else if (!logic_data_ ||
726 logic_data_->num_channels() != logic_channel_count) {
8dbbc7f0 727 logic_data_.reset(new data::Logic(
6ac6242b 728 logic_channel_count));
8dbbc7f0 729 assert(logic_data_);
b087ba7f 730 }
b087ba7f
JH
731 }
732
47e9e7bb 733 // Make the signals list
6f925ba9 734 for (shared_ptr<views::ViewBase> viewbase : views_) {
f4e57597
SA
735 views::TraceView::View *trace_view =
736 qobject_cast<views::TraceView::View*>(viewbase.get());
737
738 if (trace_view) {
739 unordered_set< shared_ptr<views::TraceView::Signal> >
740 prev_sigs(trace_view->signals());
741 trace_view->clear_signals();
742
743 for (auto channel : sr_dev->channels()) {
744 shared_ptr<data::SignalBase> signalbase;
745 shared_ptr<views::TraceView::Signal> signal;
746
747 // Find the channel in the old signals
6f925ba9 748 const auto iter = find_if(
f4e57597
SA
749 prev_sigs.cbegin(), prev_sigs.cend(),
750 [&](const shared_ptr<views::TraceView::Signal> &s) {
751 return s->base()->channel() == channel;
752 });
753 if (iter != prev_sigs.end()) {
754 // Copy the signal from the old set to the new
755 signal = *iter;
756 trace_view->add_signal(signal);
757 } else {
758 // Find the signalbase for this channel if possible
759 signalbase.reset();
760 for (const shared_ptr<data::SignalBase> b : signalbases_)
761 if (b->channel() == channel)
762 signalbase = b;
763
764 switch(channel->type()->id()) {
765 case SR_CHANNEL_LOGIC:
766 if (!signalbase) {
472a80c5
SA
767 signalbase = make_shared<data::SignalBase>(channel,
768 data::SignalBase::LogicChannel);
f4e57597
SA
769 signalbases_.insert(signalbase);
770
771 all_signal_data_.insert(logic_data_);
772 signalbase->set_data(logic_data_);
12ea3616
SA
773
774 connect(this, SIGNAL(capture_state_changed(int)),
775 signalbase.get(), SLOT(on_capture_state_changed(int)));
f4e57597
SA
776 }
777
778 signal = shared_ptr<views::TraceView::Signal>(
779 new views::TraceView::LogicSignal(*this,
780 device_, signalbase));
781 trace_view->add_signal(signal);
782 break;
783
784 case SR_CHANNEL_ANALOG:
785 {
786 if (!signalbase) {
472a80c5
SA
787 signalbase = make_shared<data::SignalBase>(channel,
788 data::SignalBase::AnalogChannel);
f4e57597
SA
789 signalbases_.insert(signalbase);
790
791 shared_ptr<data::Analog> data(new data::Analog());
792 all_signal_data_.insert(data);
793 signalbase->set_data(data);
12ea3616
SA
794
795 connect(this, SIGNAL(capture_state_changed(int)),
796 signalbase.get(), SLOT(on_capture_state_changed(int)));
f4e57597
SA
797 }
798
799 signal = shared_ptr<views::TraceView::Signal>(
800 new views::TraceView::AnalogSignal(
801 *this, signalbase));
802 trace_view->add_signal(signal);
803 break;
47e9e7bb
SA
804 }
805
f4e57597 806 default:
0402d7a3 807 assert(false);
f4e57597 808 break;
47e9e7bb 809 }
3917ba77 810 }
b087ba7f
JH
811 }
812 }
fbd3e234 813 }
b087ba7f
JH
814
815 signals_changed();
816}
817
cbd2a2de 818shared_ptr<data::SignalBase> Session::signalbase_from_channel(
bf0edd2b 819 shared_ptr<sigrok::Channel> channel) const
3ddcc083 820{
bf0edd2b 821 for (shared_ptr<data::SignalBase> sig : signalbases_) {
3ddcc083 822 assert(sig);
6ac6242b 823 if (sig->channel() == channel)
3ddcc083
JH
824 return sig;
825 }
bf0edd2b 826 return shared_ptr<data::SignalBase>();
3ddcc083
JH
827}
828
2b05d311 829void Session::sample_thread_proc(function<void (const QString)> error_handler)
274d4f13 830{
f2edb557 831 assert(error_handler);
be73bdfa 832
34c11fa7
SA
833 if (!device_)
834 return;
45f0c7c9 835
b48daed6 836 cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
274d4f13 837
e7216ae0
SA
838 out_of_memory_ = false;
839
ae2d1bc5 840 try {
5237f0c5 841 device_->start();
2ad82c2e 842 } catch (Error e) {
e8d00928 843 error_handler(e.what());
eec446e1
JH
844 return;
845 }
846
da30ecb7 847 set_capture_state(device_->session()->trigger() ?
07dcf561 848 AwaitingTrigger : Running);
eec446e1 849
da30ecb7 850 device_->run();
eec446e1 851 set_capture_state(Stopped);
1a2fe44c
JH
852
853 // Confirm that SR_DF_END was received
2ad82c2e 854 if (cur_logic_segment_) {
bb2cdfff 855 qDebug("SR_DF_END was not received.");
0402d7a3 856 assert(false);
bb2cdfff 857 }
e7216ae0 858
5e6967cb
SA
859 // Optimize memory usage
860 free_unused_memory();
861
5ccfc97e
SA
862 // We now have unsaved data unless we just "captured" from a file
863 shared_ptr<devices::File> file_device =
864 dynamic_pointer_cast<devices::File>(device_);
865
866 if (!file_device)
867 data_saved_ = false;
868
e7216ae0
SA
869 if (out_of_memory_)
870 error_handler(tr("Out of memory, acquisition stopped."));
eec446e1
JH
871}
872
5e6967cb
SA
873void Session::free_unused_memory()
874{
875 for (shared_ptr<data::SignalData> data : all_signal_data_) {
876 const vector< shared_ptr<data::Segment> > segments = data->segments();
877
878 for (shared_ptr<data::Segment> segment : segments) {
879 segment->free_unused_memory();
880 }
881 }
882}
883
da30ecb7 884void Session::feed_in_header()
eec446e1 885{
b48daed6 886 cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
be73bdfa
JH
887}
888
da30ecb7 889void Session::feed_in_meta(shared_ptr<Meta> meta)
be73bdfa 890{
e8d00928
ML
891 for (auto entry : meta->config()) {
892 switch (entry.first->id()) {
be73bdfa 893 case SR_CONF_SAMPLERATE:
8a7b603b
SA
894 // We can't rely on the header to always contain the sample rate,
895 // so in case it's supplied via a meta packet, we use it.
896 if (!cur_samplerate_)
897 cur_samplerate_ = g_variant_get_uint64(entry.second.gobj());
898
be73bdfa 899 /// @todo handle samplerate changes
be73bdfa
JH
900 break;
901 default:
902 // Unknown metadata is not an error.
903 break;
904 }
aba1dd16 905 }
74043039
JH
906
907 signals_changed();
aba1dd16
JH
908}
909
48257a69
SA
910void Session::feed_in_trigger()
911{
912 // The channel containing most samples should be most accurate
913 uint64_t sample_count = 0;
914
cc9a7898 915 {
cc9a7898
SA
916 for (const shared_ptr<pv::data::SignalData> d : all_signal_data_) {
917 assert(d);
918 uint64_t temp_count = 0;
919
920 const vector< shared_ptr<pv::data::Segment> > segments =
921 d->segments();
922 for (const shared_ptr<pv::data::Segment> &s : segments)
923 temp_count += s->get_sample_count();
924
925 if (temp_count > sample_count)
926 sample_count = temp_count;
927 }
48257a69
SA
928 }
929
930 trigger_event(sample_count / get_samplerate());
931}
932
2b81ae46 933void Session::feed_in_frame_begin()
82f50b10 934{
f3d66e52 935 if (cur_logic_segment_ || !cur_analog_segments_.empty())
82f50b10
JH
936 frame_began();
937}
938
2b81ae46 939void Session::feed_in_logic(shared_ptr<Logic> logic)
9c112671 940{
8524a597 941 lock_guard<recursive_mutex> lock(data_mutex_);
79efbc53 942
2ad82c2e 943 if (!logic_data_) {
e6c1382e
JH
944 // The only reason logic_data_ would not have been created is
945 // if it was not possible to determine the signals when the
946 // device was created.
947 update_signals();
79efbc53 948 }
be73bdfa 949
2ad82c2e 950 if (!cur_logic_segment_) {
bb2cdfff 951 // This could be the first packet after a trigger
2b49eeb0
JH
952 set_capture_state(Running);
953
f3d66e52 954 // Create a new data segment
067bb624 955 cur_logic_segment_ = make_shared<data::LogicSegment>(
04e1acc2 956 *logic_data_, logic->unit_size(), cur_samplerate_);
f3d66e52 957 logic_data_->push_segment(cur_logic_segment_);
82f50b10
JH
958
959 // @todo Putting this here means that only listeners querying
960 // for logic will be notified. Currently the only user of
961 // frame_began is DecoderStack, but in future we need to signal
962 // this after both analog and logic sweeps have begun.
963 frame_began();
9c112671
JH
964 }
965
04e1acc2
SA
966 cur_logic_segment_->append_payload(logic);
967
1f374035 968 data_received();
9c112671
JH
969}
970
2b81ae46 971void Session::feed_in_analog(shared_ptr<Analog> analog)
aba1dd16 972{
8524a597 973 lock_guard<recursive_mutex> lock(data_mutex_);
79efbc53 974
e8d00928
ML
975 const vector<shared_ptr<Channel>> channels = analog->channels();
976 const unsigned int channel_count = channels.size();
977 const size_t sample_count = analog->num_samples() / channel_count;
475f4d08 978 const float *data = static_cast<const float *>(analog->data_pointer());
bb2cdfff 979 bool sweep_beginning = false;
be73bdfa 980
47e9e7bb 981 if (signalbases_.empty())
a3f678a7 982 update_signals();
a3f678a7 983
2ad82c2e 984 for (auto channel : channels) {
f3d66e52 985 shared_ptr<data::AnalogSegment> segment;
2b49eeb0 986
f3d66e52
JH
987 // Try to get the segment of the channel
988 const map< shared_ptr<Channel>, shared_ptr<data::AnalogSegment> >::
989 iterator iter = cur_analog_segments_.find(channel);
990 if (iter != cur_analog_segments_.end())
991 segment = (*iter).second;
2ad82c2e 992 else {
39ccf9c3 993 // If no segment was found, this means we haven't
bb2cdfff 994 // created one yet. i.e. this is the first packet
f3d66e52 995 // in the sweep containing this segment.
bb2cdfff
JH
996 sweep_beginning = true;
997
ff4bf6bd 998 // Find the analog data associated with the channel
cbd2a2de
SA
999 shared_ptr<data::SignalBase> base = signalbase_from_channel(channel);
1000 assert(base);
bb2cdfff 1001
cbd2a2de 1002 shared_ptr<data::Analog> data(base->analog_data());
bb2cdfff
JH
1003 assert(data);
1004
7db61e77 1005 // Create a segment, keep it in the maps of channels
067bb624
UH
1006 segment = make_shared<data::AnalogSegment>(
1007 *data, cur_samplerate_);
7db61e77
SA
1008 cur_analog_segments_[channel] = segment;
1009
f3d66e52
JH
1010 // Push the segment into the analog data.
1011 data->push_segment(segment);
bb2cdfff
JH
1012 }
1013
f3d66e52 1014 assert(segment);
bb2cdfff 1015
f3d66e52
JH
1016 // Append the samples in the segment
1017 segment->append_interleaved_samples(data++, sample_count,
6ac6242b 1018 channel_count);
aba1dd16 1019 }
bb2cdfff
JH
1020
1021 if (sweep_beginning) {
1022 // This could be the first packet after a trigger
1023 set_capture_state(Running);
aba1dd16
JH
1024 }
1025
1f374035 1026 data_received();
aba1dd16 1027}
9c112671 1028
da30ecb7
JH
1029void Session::data_feed_in(shared_ptr<sigrok::Device> device,
1030 shared_ptr<Packet> packet)
b0e1d01d 1031{
c063290a 1032 static bool frame_began = false;
0a4162a4 1033
da30ecb7
JH
1034 (void)device;
1035
e8d00928 1036 assert(device);
da30ecb7 1037 assert(device == device_->device());
b0e1d01d
JH
1038 assert(packet);
1039
e8d00928 1040 switch (packet->type()->id()) {
b0e1d01d 1041 case SR_DF_HEADER:
da30ecb7 1042 feed_in_header();
b0e1d01d
JH
1043 break;
1044
be73bdfa 1045 case SR_DF_META:
da30ecb7 1046 feed_in_meta(dynamic_pointer_cast<Meta>(packet->payload()));
aba1dd16
JH
1047 break;
1048
48257a69
SA
1049 case SR_DF_TRIGGER:
1050 feed_in_trigger();
1051 break;
1052
82f50b10
JH
1053 case SR_DF_FRAME_BEGIN:
1054 feed_in_frame_begin();
0a4162a4 1055 frame_began = true;
82f50b10
JH
1056 break;
1057
2e2946fe 1058 case SR_DF_LOGIC:
e7216ae0
SA
1059 try {
1060 feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
6f925ba9 1061 } catch (bad_alloc) {
e7216ae0
SA
1062 out_of_memory_ = true;
1063 device_->stop();
1064 }
2953961c
JH
1065 break;
1066
aba1dd16 1067 case SR_DF_ANALOG:
e7216ae0
SA
1068 try {
1069 feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
6f925ba9 1070 } catch (bad_alloc) {
e7216ae0
SA
1071 out_of_memory_ = true;
1072 device_->stop();
1073 }
aba1dd16
JH
1074 break;
1075
0a4162a4 1076 case SR_DF_FRAME_END:
2953961c 1077 case SR_DF_END:
2e2946fe
JH
1078 {
1079 {
8524a597 1080 lock_guard<recursive_mutex> lock(data_mutex_);
f3d66e52
JH
1081 cur_logic_segment_.reset();
1082 cur_analog_segments_.clear();
2e2946fe 1083 }
0a4162a4
SA
1084 if (frame_began) {
1085 frame_began = false;
1086 frame_ended();
1087 }
2953961c
JH
1088 break;
1089 }
adb0a983
ML
1090 default:
1091 break;
2e2946fe 1092 }
2953961c
JH
1093}
1094
5ccfc97e
SA
1095void Session::on_data_saved()
1096{
1097 data_saved_ = true;
1098}
1099
51e77110 1100} // namespace pv