Main: Add -s option to allow logging to console as before
[pulseview.git] / pv / session.hpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2012-14 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifndef PULSEVIEW_PV_SESSION_HPP
21 #define PULSEVIEW_PV_SESSION_HPP
22
23 #include <functional>
24 #include <map>
25 #include <memory>
26 #include <mutex>
27 #include <set>
28 #include <string>
29 #include <thread>
30 #include <unordered_set>
31 #include <vector>
32
33 #include <QObject>
34 #include <QSettings>
35 #include <QString>
36
37 #include "util.hpp"
38 #include "views/viewbase.hpp"
39
40 using std::function;
41 using std::list;
42 using std::map;
43 using std::mutex;
44 using std::recursive_mutex;
45 using std::shared_ptr;
46 using std::string;
47 using std::unordered_set;
48
49 struct srd_decoder;
50 struct srd_channel;
51
52 namespace sigrok {
53 class Analog;
54 class Channel;
55 class Device;
56 class InputFormat;
57 class Logic;
58 class Meta;
59 class Option;
60 class OutputFormat;
61 class Packet;
62 class Session;
63 }  // namespace sigrok
64
65 using sigrok::Option;
66
67 namespace pv {
68
69 class DeviceManager;
70
71 namespace data {
72 class Analog;
73 class AnalogSegment;
74 class DecodeSignal;
75 class Logic;
76 class LogicSegment;
77 class SignalBase;
78 class SignalData;
79 }
80
81 namespace devices {
82 class Device;
83 }
84
85 namespace toolbars {
86 class MainBar;
87 }
88
89 namespace views {
90 class ViewBase;
91 }
92
93 class Session : public QObject
94 {
95         Q_OBJECT
96
97 public:
98         enum capture_state {
99                 Stopped,
100                 AwaitingTrigger,
101                 Running
102         };
103
104         static shared_ptr<sigrok::Context> sr_context;
105
106 public:
107         Session(DeviceManager &device_manager, QString name);
108
109         ~Session();
110
111         DeviceManager& device_manager();
112
113         const DeviceManager& device_manager() const;
114
115         shared_ptr<sigrok::Session> session() const;
116
117         shared_ptr<devices::Device> device() const;
118
119         QString name() const;
120
121         void set_name(QString name);
122
123         const list< shared_ptr<views::ViewBase> > views() const;
124
125         shared_ptr<views::ViewBase> main_view() const;
126
127         shared_ptr<pv::toolbars::MainBar> main_bar() const;
128
129         void set_main_bar(shared_ptr<pv::toolbars::MainBar> main_bar);
130
131         /**
132          * Indicates whether the captured data was saved to disk already or not
133          */
134         bool data_saved() const;
135
136         void save_settings(QSettings &settings) const;
137
138         void restore_settings(QSettings &settings);
139
140         /**
141          * Attempts to set device instance, may fall back to demo if needed
142          */
143         void select_device(shared_ptr<devices::Device> device);
144
145         /**
146          * Sets device instance that will be used in the next capture session.
147          */
148         void set_device(shared_ptr<devices::Device> device);
149
150         void set_default_device();
151
152         void load_init_file(const string &file_name, const string &format);
153
154         void load_file(QString file_name,
155                 shared_ptr<sigrok::InputFormat> format = nullptr,
156                 const map<string, Glib::VariantBase> &options =
157                         map<string, Glib::VariantBase>());
158
159         capture_state get_capture_state() const;
160
161         void start_capture(function<void (const QString)> error_handler);
162
163         void stop_capture();
164
165         double get_samplerate() const;
166
167         uint32_t get_segment_count() const;
168
169         vector<util::Timestamp> get_triggers(uint32_t segment_id) const;
170
171         void register_view(shared_ptr<views::ViewBase> view);
172
173         void deregister_view(shared_ptr<views::ViewBase> view);
174
175         bool has_view(shared_ptr<views::ViewBase> view);
176
177         const unordered_set< shared_ptr<data::SignalBase> > signalbases() const;
178
179         bool all_segments_complete(uint32_t segment_id) const;
180
181 #ifdef ENABLE_DECODE
182         shared_ptr<data::DecodeSignal> add_decode_signal();
183
184         void remove_decode_signal(shared_ptr<data::DecodeSignal> signal);
185 #endif
186
187 private:
188         void set_capture_state(capture_state state);
189
190         void update_signals();
191
192         shared_ptr<data::SignalBase> signalbase_from_channel(
193                 shared_ptr<sigrok::Channel> channel) const;
194
195         static map<string, Glib::VariantBase> input_format_options(
196                 vector<string> user_spec,
197                 map<string, shared_ptr<Option>> fmt_opts);
198
199         void sample_thread_proc(function<void (const QString)> error_handler);
200
201         void free_unused_memory();
202
203         void signal_new_segment();
204         void signal_segment_completed();
205
206         void feed_in_header();
207
208         void feed_in_meta(shared_ptr<sigrok::Meta> meta);
209
210         void feed_in_trigger();
211
212         void feed_in_frame_begin();
213         void feed_in_frame_end();
214
215         void feed_in_logic(shared_ptr<sigrok::Logic> logic);
216
217         void feed_in_analog(shared_ptr<sigrok::Analog> analog);
218
219         void data_feed_in(shared_ptr<sigrok::Device> device,
220                 shared_ptr<sigrok::Packet> packet);
221
222 Q_SIGNALS:
223         void capture_state_changed(int state);
224         void device_changed();
225
226         void signals_changed();
227
228         void name_changed();
229
230         void trigger_event(int segment_id, util::Timestamp location);
231
232         void new_segment(int new_segment_id);
233         void segment_completed(int segment_id);
234
235         void data_received();
236
237         void add_view(const QString &title, views::ViewType type,
238                 Session *session);
239
240 public Q_SLOTS:
241         void on_data_saved();
242
243 private:
244         DeviceManager &device_manager_;
245         shared_ptr<devices::Device> device_;
246         QString default_name_, name_;
247
248         list< shared_ptr<views::ViewBase> > views_;
249         shared_ptr<pv::views::ViewBase> main_view_;
250
251         shared_ptr<pv::toolbars::MainBar> main_bar_;
252
253         mutable mutex sampling_mutex_; //!< Protects access to capture_state_.
254         capture_state capture_state_;
255
256         unordered_set< shared_ptr<data::SignalBase> > signalbases_;
257         unordered_set< shared_ptr<data::SignalData> > all_signal_data_;
258
259         /// trigger_list_ contains pairs of <segment_id, timestamp> values.
260         vector< std::pair<uint32_t, util::Timestamp> > trigger_list_;
261
262         mutable recursive_mutex data_mutex_;
263         shared_ptr<data::Logic> logic_data_;
264         uint64_t cur_samplerate_;
265         shared_ptr<data::LogicSegment> cur_logic_segment_;
266         map< shared_ptr<sigrok::Channel>, shared_ptr<data::AnalogSegment> >
267                 cur_analog_segments_;
268         int32_t highest_segment_id_;
269
270         std::thread sampling_thread_;
271
272         bool out_of_memory_;
273         bool data_saved_;
274         bool frame_began_;
275 };
276
277 } // namespace pv
278
279 #endif // PULSEVIEW_PV_SESSION_HPP