]> sigrok.org Git - pulseview.git/blob - pv/storesession.cpp
Moved all sr_probe modification into pv::DevInst
[pulseview.git] / pv / storesession.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include "storesession.h"
22
23 #include <pv/sigsession.h>
24 #include <pv/data/logic.h>
25 #include <pv/data/logicsnapshot.h>
26 #include <pv/view/signal.h>
27
28 using boost::dynamic_pointer_cast;
29 using boost::mutex;
30 using boost::shared_ptr;
31 using boost::thread;
32 using boost::lock_guard;
33 using std::deque;
34 using std::make_pair;
35 using std::min;
36 using std::pair;
37 using std::set;
38 using std::string;
39 using std::vector;
40
41 namespace pv {
42
43 const size_t StoreSession::BlockSize = 1024 * 1024;
44
45 StoreSession::StoreSession(const std::string &file_name,
46         const SigSession &session) :
47         _file_name(file_name),
48         _session(session),
49         _units_stored(0),
50         _unit_count(0)
51 {
52 }
53
54 StoreSession::~StoreSession()
55 {
56         wait();
57 }
58
59 pair<uint64_t, uint64_t> StoreSession::progress() const
60 {
61         lock_guard<mutex> lock(_mutex);
62         return make_pair(_units_stored, _unit_count);
63 }
64
65 const QString& StoreSession::error() const
66 {
67         lock_guard<mutex> lock(_mutex);
68         return _error;
69 }
70
71 bool StoreSession::start()
72 {
73         set< shared_ptr<data::SignalData> > data_set =
74                 _session.get_data();
75         const vector< shared_ptr<view::Signal> > sigs =
76                 _session.get_signals();
77
78         // Check we have logic data
79         if (data_set.empty() || sigs.empty()) {
80                 _error = tr("No data to save.");
81                 return false;
82         }
83
84         if (data_set.size() > 1) {
85                 _error = tr("PulseView currently only has support for "
86                         "storing a single data stream.");
87                 return false;
88         }
89
90         // Get the logic data
91         //shared_ptr<data::SignalData
92         shared_ptr<data::Logic> data;
93         if (!(data = dynamic_pointer_cast<data::Logic>(*data_set.begin()))) {
94                 _error = tr("PulseView currently only has support for "
95                         "storing a logic data.");
96                 return false;
97         }
98
99         // Get the snapshot
100         const deque< shared_ptr<data::LogicSnapshot> > &snapshots =
101                 data->get_snapshots();
102
103         if (snapshots.empty()) {
104                 _error = tr("No snapshots to save.");
105                 return false;
106         }
107
108         const shared_ptr<data::LogicSnapshot> snapshot(snapshots.front());
109         assert(snapshot);
110
111         // Make a list of probes
112         char **const probes = new char*[sigs.size() + 1];
113         for (size_t i = 0; i < sigs.size(); i++) {
114                 shared_ptr<view::Signal> sig(sigs[i]);
115                 assert(sig);
116                 probes[i] = strdup(sig->get_name().toUtf8().constData());
117         }
118         probes[sigs.size()] = NULL;
119
120         // Begin storing
121         if (sr_session_save_init(_file_name.c_str(),
122                 data->samplerate(), probes) != SR_OK) {
123                 _error = tr("Error while saving.");
124                 return false;
125         }
126
127         // Delete the probes array
128         for (size_t i = 0; i <= sigs.size(); i++)
129                 free(probes[i]);
130         delete[] probes;
131
132         _thread = boost::thread(&StoreSession::store_proc, this, snapshot);
133         return true;
134 }
135
136 void StoreSession::wait()
137 {
138         _thread.join();
139 }
140
141 void StoreSession::cancel()
142 {
143         _thread.interrupt();
144 }
145
146 void StoreSession::store_proc(shared_ptr<data::LogicSnapshot> snapshot)
147 {
148         assert(snapshot);
149
150         uint64_t start_sample = 0;
151
152         /// TODO: Wrap this in a std::unique_ptr when we transition to C++11
153         uint8_t *const data = new uint8_t[BlockSize];
154         assert(data);
155
156         const int unit_size = snapshot->unit_size();
157         assert(unit_size != 0);
158
159         {
160                 lock_guard<mutex> lock(_mutex);
161                 _unit_count = snapshot->get_sample_count();
162         }
163
164         const unsigned int samples_per_block = BlockSize / unit_size;
165
166         while (!boost::this_thread::interruption_requested() &&
167                 start_sample < _unit_count)
168         {
169                 progress_updated();
170
171                 const uint64_t end_sample = min(
172                         start_sample + samples_per_block, _unit_count);
173                 snapshot->get_samples(data, start_sample, end_sample);
174
175                 if(sr_session_append(_file_name.c_str(), data, unit_size,
176                         end_sample - start_sample) != SR_OK)
177                 {
178                         _error = tr("Error while saving.");
179                         break;
180                 }
181
182                 start_sample = end_sample;
183
184                 {
185                         lock_guard<mutex> lock(_mutex);
186                         _units_stored = start_sample;
187                 }
188         }
189
190         progress_updated();
191
192         delete[] data;
193 }
194
195 } // pv