]> sigrok.org Git - pulseview.git/blob - pv/sigsession.cpp
Keep Run/Stop button state updated
[pulseview.git] / pv / sigsession.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2012 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 "sigsession.h"
22
23 #include "logicdata.h"
24 #include "logicdatasnapshot.h"
25 #include "view/logicsignal.h"
26
27 #include <QDebug>
28
29 #include <assert.h>
30
31 using namespace boost;
32 using namespace std;
33
34 namespace pv {
35
36 // TODO: This should not be necessary
37 SigSession* SigSession::_session = NULL;
38
39 SigSession::SigSession() :
40         _capture_state(Stopped)
41 {
42         // TODO: This should not be necessary
43         _session = this;
44 }
45
46 SigSession::~SigSession()
47 {
48         stop_capture();
49
50         if(_sampling_thread.get())
51                 _sampling_thread->join();
52         _sampling_thread.reset();
53
54         // TODO: This should not be necessary
55         _session = NULL;
56 }
57
58 void SigSession::load_file(const std::string &name)
59 {
60         if (sr_session_load(name.c_str()) == SR_OK) {
61                 /* sigrok session file */
62                 sr_session_datafeed_callback_add(data_feed_in_proc);
63                 sr_session_start();
64                 sr_session_run();
65                 sr_session_stop();
66         }
67 }
68
69 SigSession::capture_state SigSession::get_capture_state() const
70 {
71         lock_guard<mutex> lock(_state_mutex);
72         return _capture_state;
73 }
74
75 void SigSession::start_capture(struct sr_dev_inst *sdi,
76         uint64_t record_length, uint64_t sample_rate)
77 {
78         stop_capture();
79
80
81         _sampling_thread.reset(new boost::thread(
82                 &SigSession::sample_thread_proc, this, sdi,
83                 record_length, sample_rate));
84 }
85
86 void SigSession::stop_capture()
87 {
88         if(get_capture_state() == Stopped)
89                 return;
90
91         sr_session_stop();
92
93         // Check that sampling stopped
94         if(_sampling_thread.get())
95                 _sampling_thread->join();
96         _sampling_thread.reset();
97 }
98
99 vector< shared_ptr<view::Signal> > SigSession::get_signals()
100 {
101         lock_guard<mutex> lock(_signals_mutex);
102         return _signals;
103 }
104
105 boost::shared_ptr<LogicData> SigSession::get_data()
106 {
107         return _logic_data;
108 }
109
110 void SigSession::set_capture_state(capture_state state)
111 {
112         lock_guard<mutex> lock(_state_mutex);
113         _capture_state = state;
114         capture_state_changed(state);
115 }
116
117 void SigSession::sample_thread_proc(struct sr_dev_inst *sdi,
118         uint64_t record_length, uint64_t sample_rate)
119 {
120         sr_session_new();
121         sr_session_datafeed_callback_add(data_feed_in_proc);
122
123         if (sr_session_dev_add(sdi) != SR_OK) {
124                 qDebug() << "Failed to use device.";
125                 sr_session_destroy();
126                 return;
127         }
128
129         if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES,
130                 &record_length) != SR_OK) {
131                 qDebug() << "Failed to configure time-based sample limit.";
132                 sr_session_destroy();
133                 return;
134         }
135
136         if (sr_dev_config_set(sdi, SR_HWCAP_SAMPLERATE,
137                 &sample_rate) != SR_OK) {
138                 qDebug() << "Failed to configure samplerate.";
139                 sr_session_destroy();
140                 return;
141         }
142
143         if (sr_session_start() != SR_OK) {
144                 qDebug() << "Failed to start session.";
145                 return;
146         }
147
148         set_capture_state(Running);
149
150         sr_session_run();
151         sr_session_destroy();
152
153         set_capture_state(Stopped);
154 }
155
156 void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
157         struct sr_datafeed_packet *packet)
158 {
159         using view::LogicSignal;
160
161         assert(sdi);
162         assert(packet);
163
164         switch (packet->type) {
165         case SR_DF_HEADER:
166         {
167                 lock_guard<mutex> lock(_signals_mutex);
168                 _signals.clear();
169                 break;
170         }
171
172         case SR_DF_META_LOGIC:
173         {
174                 assert(packet->payload);
175                 const sr_datafeed_meta_logic &meta_logic =
176                         *(sr_datafeed_meta_logic*)packet->payload;
177
178         {
179                 lock_guard<mutex> lock(_data_mutex);
180
181                 // Create an empty LogiData for coming data snapshots
182                 _logic_data.reset(new LogicData(meta_logic));
183                 assert(_logic_data);
184                 if(!_logic_data)
185                         break;
186         }
187
188         {
189                 lock_guard<mutex> lock(_signals_mutex);
190
191                 // Add the signals
192                 for (int i = 0; i < meta_logic.num_probes; i++)
193                 {
194                         const sr_probe *const probe =
195                                 (const sr_probe*)g_slist_nth_data(
196                                         sdi->probes, i);
197                         if(probe->enabled)
198                         {
199                                 shared_ptr<LogicSignal> signal(
200                                         new LogicSignal(probe->name,
201                                                 _logic_data,
202                                                 probe->index));
203                                 _signals.push_back(signal);
204                         }
205                 }
206
207                 signals_changed();
208                 break;
209         }
210         }
211
212         case SR_DF_LOGIC:
213         {
214                 lock_guard<mutex> lock(_data_mutex);
215                 assert(packet->payload);
216                 if(!_cur_logic_snapshot)
217                 {
218                         // Create a new data snapshot
219                         _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
220                                 new LogicDataSnapshot(
221                                 *(sr_datafeed_logic*)packet->payload));
222                         _logic_data->push_snapshot(_cur_logic_snapshot);
223                 }
224                 else
225                 {
226                         // Append to the existing data snapshot
227                         _cur_logic_snapshot->append_payload(
228                                 *(sr_datafeed_logic*)packet->payload);
229                 }
230
231                 data_updated();
232                 break;
233         }
234
235         case SR_DF_END:
236         {
237                 {
238                         lock_guard<mutex> lock(_data_mutex);
239                         _cur_logic_snapshot.reset();
240                 }
241                 data_updated();
242                 break;
243         }
244         }
245 }
246
247 void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi,
248         struct sr_datafeed_packet *packet)
249 {
250         assert(_session);
251         _session->data_feed_in(sdi, packet);
252 }
253
254 } // namespace pv