]> sigrok.org Git - pulseview.git/blame - pv/devices/inputfile.cpp
GlobalSettings: Always use Fusion style on Windows for dark themes
[pulseview.git] / pv / devices / inputfile.cpp
CommitLineData
5237f0c5
JH
1/*
2 * This file is part of the PulseView project.
3 *
4 * Copyright (C) 2015 Joel Holdsworth <joel@airwebreathe.org.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
efdec55a 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
5237f0c5
JH
18 */
19
20#include <cassert>
21#include <fstream>
3b0acbcb 22#include <vector>
5237f0c5 23
1325ce42 24#include <QDebug>
5237f0c5
JH
25#include <QString>
26
1325ce42
SA
27#include <pv/globalsettings.hpp>
28
5237f0c5
JH
29#include "inputfile.hpp"
30
1325ce42
SA
31using sigrok::InputFormat;
32
6f925ba9 33using std::map;
1325ce42
SA
34using std::out_of_range;
35using std::pair;
6f925ba9
UH
36using std::shared_ptr;
37using std::streamsize;
38using std::string;
39using std::ifstream;
40using std::ios;
3b0acbcb 41using std::vector;
6f925ba9 42
5237f0c5
JH
43namespace pv {
44namespace devices {
45
1f419596
UH
46// Use a 4MB chunk size for reading a file into memory. Larger values don't
47// seem to provide any substancial performance improvements, but can cause
48// UI lag and a visually "stuttering" display of the data currently loading.
49const streamsize InputFile::BufferSize = (4 * 1024 * 1024);
5237f0c5 50
6f925ba9
UH
51InputFile::InputFile(const shared_ptr<sigrok::Context> &context,
52 const string &file_name,
53 shared_ptr<sigrok::InputFormat> format,
54 const map<string, Glib::VariantBase> &options) :
dd3fd4df 55 File(file_name),
5237f0c5 56 context_(context),
519d0ccb
SA
57 format_(format),
58 options_(options),
2ad82c2e
UH
59 interrupt_(false)
60{
5237f0c5
JH
61}
62
1325ce42
SA
63InputFile::InputFile(const shared_ptr<sigrok::Context> &context,
64 QSettings &settings):
65 File(""),
66 context_(context),
67 interrupt_(false)
68{
69 file_name_ = settings.value("filename").toString().toStdString();
70
71 QString format_name = settings.value("format").toString();
72
73 // Find matching format
74 const map<string, shared_ptr<InputFormat> > formats = context->input_formats();
75
76 try {
77 format_ = formats.at(format_name.toStdString());
78
79 // Restore all saved options
80 int options = settings.value("options").toInt();
81
82 for (int i = 0; i < options; i++) {
83 settings.beginGroup("option" + QString::number(i));
84 QString name = settings.value("name").toString();
85 options_[name.toStdString()] = GlobalSettings::restore_variantbase(settings);
86 settings.endGroup();
87 }
88
16a832bc 89 } catch (out_of_range&) {
1325ce42
SA
90 qWarning() << "Could not find input format" << format_name <<
91 "needed to restore session input file";
92 }
93}
94
95void InputFile::save_meta_to_settings(QSettings &settings)
96{
97 settings.setValue("filename", QString::fromStdString(file_name_));
98
99 settings.setValue("format", QString::fromStdString(format_->name()));
100
101 settings.setValue("options", (int)options_.size());
102
103 int i = 0;
f4ab4b5c 104 for (const pair<string, Glib::VariantBase>& option : options_) {
1325ce42
SA
105 settings.beginGroup("option" + QString::number(i));
106 settings.setValue("name", QString::fromStdString(option.first));
107 GlobalSettings::store_variantbase(settings, option.second);
108 settings.endGroup();
109 i++;
110 }
111}
112
2ad82c2e
UH
113void InputFile::open()
114{
4d6c6ea3
SA
115 if (session_)
116 close();
519d0ccb
SA
117 else
118 session_ = context_->create_session();
cda51567 119
1325ce42
SA
120 if (!format_)
121 return;
122
cda51567
SA
123 input_ = format_->create_input(options_);
124
125 if (!input_)
126 throw QString("Failed to create input");
127
128 // open() should add the input device to the session but
129 // we can't open the device without sending some data first
6f925ba9 130 f = new ifstream(file_name_, ios::binary);
cda51567 131
3b0acbcb
UH
132 vector<char> buffer(BufferSize);
133
134 f->read(buffer.data(), BufferSize);
6f925ba9 135 const streamsize size = f->gcount();
ea50cdfc 136
cda51567 137 if (size == 0)
ea50cdfc 138 throw QString("Failed to read file");
cda51567 139
3b0acbcb 140 input_->send(buffer.data(), size);
cda51567
SA
141
142 try {
143 device_ = input_->device();
ea50cdfc
SA
144 } catch (sigrok::Error& e) {
145 throw e;
cda51567
SA
146 }
147
148 session_->add_device(device_);
5237f0c5
JH
149}
150
2ad82c2e
UH
151void InputFile::close()
152{
4d6c6ea3
SA
153 if (session_)
154 session_->remove_devices();
155}
156
2ad82c2e
UH
157void InputFile::start()
158{
5237f0c5
JH
159}
160
2ad82c2e
UH
161void InputFile::run()
162{
1325ce42
SA
163 if (!input_)
164 return;
165
cda51567
SA
166 if (!f) {
167 // Previous call to run() processed the entire file already
6f925ba9 168 f = new ifstream(file_name_, ios::binary);
cda51567
SA
169 input_->reset();
170 }
5237f0c5 171
3b0acbcb
UH
172 vector<char> buffer(BufferSize);
173
5237f0c5 174 interrupt_ = false;
cda51567 175 while (!interrupt_ && !f->eof()) {
3b0acbcb 176 f->read(buffer.data(), BufferSize);
6f925ba9 177 const streamsize size = f->gcount();
5237f0c5
JH
178 if (size == 0)
179 break;
180
3b0acbcb 181 input_->send(buffer.data(), size);
5237f0c5 182
5237f0c5
JH
183 if (size != BufferSize)
184 break;
185 }
186
187 input_->end();
cda51567
SA
188
189 delete f;
190 f = nullptr;
5237f0c5
JH
191}
192
2ad82c2e
UH
193void InputFile::stop()
194{
5237f0c5
JH
195 interrupt_ = true;
196}
197
198} // namespace devices
199} // namespace pv