]> sigrok.org Git - pulseview.git/blob - pv/toolbars/samplingbar.cpp
0754f001e9a1828b3cd2fa66e7d8d9ee497da330
[pulseview.git] / pv / toolbars / samplingbar.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 <extdef.h>
22
23 #include <assert.h>
24
25 #include <boost/foreach.hpp>
26
27 #include <libsigrok/libsigrok.h>
28
29 #include <QAction>
30 #include <QDebug>
31
32 #include "samplingbar.h"
33
34 #include <pv/devicemanager.h>
35 #include <pv/dialogs/deviceoptions.h>
36
37 using namespace std;
38
39 namespace pv {
40 namespace toolbars {
41
42 const uint64_t SamplingBar::RecordLengths[20] = {
43         1000,
44         2500,
45         5000,
46         10000,
47         25000,
48         50000,
49         100000,
50         250000,
51         500000,
52         1000000,
53         2000000,
54         5000000,
55         10000000,
56         25000000,
57         50000000,
58         100000000,
59         250000000,
60         500000000,
61         1000000000,
62         10000000000ULL,
63 };
64
65 const uint64_t SamplingBar::DefaultRecordLength = 1000000;
66
67 SamplingBar::SamplingBar(QWidget *parent) :
68         QToolBar("Sampling Bar", parent),
69         _device_selector(this),
70         _configure_button(this),
71         _record_length_selector(this),
72         _sample_rate_list(this),
73         _icon_green(":/icons/status-green.svg"),
74         _icon_grey(":/icons/status-grey.svg"),
75         _run_stop_button(this)
76 {
77         connect(&_run_stop_button, SIGNAL(clicked()),
78                 this, SLOT(on_run_stop()));
79         connect(&_device_selector, SIGNAL(currentIndexChanged (int)),
80                 this, SLOT(on_device_selected()));
81         connect(&_configure_button, SIGNAL(clicked()),
82                 this, SLOT(on_configure()));
83
84         _sample_rate_value.setDecimals(0);
85         _sample_rate_value.setSuffix("Hz");
86
87         for (size_t i = 0; i < countof(RecordLengths); i++)
88         {
89                 const uint64_t &l = RecordLengths[i];
90                 char *const text = sr_si_string_u64(l, " samples");
91                 _record_length_selector.addItem(QString(text),
92                         qVariantFromValue(l));
93                 g_free(text);
94
95                 if (l == DefaultRecordLength)
96                         _record_length_selector.setCurrentIndex(i);
97         }
98
99         set_sampling(false);
100
101         _configure_button.setIcon(QIcon::fromTheme("configure",
102                 QIcon(":/icons/configure.png")));
103
104         _run_stop_button.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
105
106         addWidget(&_device_selector);
107         addWidget(&_configure_button);
108         addWidget(&_record_length_selector);
109         _sample_rate_list_action = addWidget(&_sample_rate_list);
110         _sample_rate_value_action = addWidget(&_sample_rate_value);
111         addWidget(&_run_stop_button);
112
113         connect(&_sample_rate_list, SIGNAL(currentIndexChanged(int)),
114                 this, SLOT(on_sample_rate_changed()));
115         connect(&_sample_rate_value, SIGNAL(editingFinished()),
116                 this, SLOT(on_sample_rate_changed()));
117 }
118
119 void SamplingBar::set_device_list(
120         const std::list<struct sr_dev_inst*> &devices)
121 {
122         _device_selector.clear();
123
124         BOOST_FOREACH (sr_dev_inst *sdi, devices) {
125                 const string title = DeviceManager::format_device_title(sdi);
126                 _device_selector.addItem(title.c_str(),
127                         qVariantFromValue((void*)sdi));
128         }
129
130         update_sample_rate_selector();
131 }
132
133 struct sr_dev_inst* SamplingBar::get_selected_device() const
134 {
135         const int index = _device_selector.currentIndex();
136         if (index < 0)
137                 return NULL;
138
139         return (sr_dev_inst*)_device_selector.itemData(
140                 index).value<void*>();
141 }
142
143 void SamplingBar::set_selected_device(struct sr_dev_inst *const sdi)
144 {
145         for (int i = 0; i < _device_selector.count(); i++)
146                 if (sdi == _device_selector.itemData(i).value<void*>()) {
147                         _device_selector.setCurrentIndex(i);
148                         return;
149                 }
150 }
151
152 uint64_t SamplingBar::get_record_length() const
153 {
154         const int index = _record_length_selector.currentIndex();
155         if (index < 0)
156                 return 0;
157
158         return _record_length_selector.itemData(index).value<uint64_t>();
159 }
160
161 void SamplingBar::set_sampling(bool sampling)
162 {
163         _run_stop_button.setIcon(sampling ? _icon_green : _icon_grey);
164         _run_stop_button.setText(sampling ? "Stop" : "Run");
165 }
166
167 void SamplingBar::update_sample_rate_selector()
168 {
169         const sr_dev_inst *const sdi = get_selected_device();
170         GVariant *gvar_dict, *gvar_list;
171         const uint64_t *elements = NULL;
172         gsize num_elements;
173         QAction *selector_action = NULL;
174
175         assert(_sample_rate_value_action);
176         assert(_sample_rate_list_action);
177
178         if (!sdi)
179                 return;
180
181         if (sr_config_list(sdi->driver, SR_CONF_SAMPLERATE,
182                         &gvar_dict, sdi) != SR_OK)
183                 return;
184
185         _sample_rate_list_action->setVisible(false);
186         _sample_rate_value_action->setVisible(false);
187
188         if ((gvar_list = g_variant_lookup_value(gvar_dict,
189                         "samplerate-steps", G_VARIANT_TYPE("at")))) {
190                 elements = (const uint64_t *)g_variant_get_fixed_array(
191                                 gvar_list, &num_elements, sizeof(uint64_t));
192                 _sample_rate_value.setRange(elements[0], elements[1]);
193                 _sample_rate_value.setSingleStep(elements[2]);
194                 g_variant_unref(gvar_list);
195
196                 selector_action = _sample_rate_value_action;
197         }
198         else if ((gvar_list = g_variant_lookup_value(gvar_dict,
199                         "samplerates", G_VARIANT_TYPE("at"))))
200         {
201                 elements = (const uint64_t *)g_variant_get_fixed_array(
202                                 gvar_list, &num_elements, sizeof(uint64_t));
203                 _sample_rate_list.clear();
204
205                 for (unsigned int i = 0; i < num_elements; i++)
206                 {
207                         char *const s = sr_samplerate_string(elements[i]);
208                         _sample_rate_list.addItem(QString(s),
209                                 qVariantFromValue(elements[i]));
210                         g_free(s);
211                 }
212
213                 _sample_rate_list.show();
214                 g_variant_unref(gvar_list);
215
216                 selector_action = _sample_rate_list_action;
217         }
218
219         g_variant_unref(gvar_dict);
220         update_sample_rate_selector_value();
221
222         // We delay showing the action, so that value change events
223         // are ignored.
224         if (selector_action)
225                 selector_action->setVisible(true);
226 }
227
228 void SamplingBar::update_sample_rate_selector_value()
229 {
230         sr_dev_inst *const sdi = get_selected_device();
231         GVariant *gvar;
232         uint64_t samplerate;
233
234         assert(sdi);
235
236         if (sr_config_get(sdi->driver, SR_CONF_SAMPLERATE,
237                 &gvar, sdi) != SR_OK) {
238                 qDebug() <<
239                                 "WARNING: Failed to get value of sample rate";
240                 return;
241         }
242         samplerate = g_variant_get_uint64(gvar);
243         g_variant_unref(gvar);
244
245         assert(_sample_rate_value_action);
246         assert(_sample_rate_list_action);
247
248         if (_sample_rate_value_action->isVisible())
249                 _sample_rate_value.setValue(samplerate);
250         else if (_sample_rate_list_action->isVisible())
251         {
252                 for (int i = 0; i < _sample_rate_list.count(); i++)
253                         if (samplerate == _sample_rate_list.itemData(
254                                 i).value<uint64_t>())
255                                 _sample_rate_list.setCurrentIndex(i);
256         }
257 }
258
259 void SamplingBar::commit_sample_rate()
260 {
261         uint64_t sample_rate = 0;
262
263         sr_dev_inst *const sdi = get_selected_device();
264         assert(sdi);
265
266         assert(_sample_rate_value_action);
267         assert(_sample_rate_list_action);
268
269         if (_sample_rate_value_action->isVisible())
270                 sample_rate = (uint64_t)_sample_rate_value.value();
271         else if (_sample_rate_list_action->isVisible())
272         {
273                 const int index = _sample_rate_list.currentIndex();
274                 if (index >= 0)
275                         sample_rate = _sample_rate_list.itemData(
276                                 index).value<uint64_t>();
277         }
278
279         if (sample_rate == 0)
280                 return;
281
282         // Set the samplerate
283         if (sr_config_set(sdi, SR_CONF_SAMPLERATE,
284                 g_variant_new_uint64(sample_rate)) != SR_OK) {
285                 qDebug() << "Failed to configure samplerate.";
286                 return;
287         }
288 }
289
290 void SamplingBar::on_device_selected()
291 {
292         update_sample_rate_selector();
293         device_selected();
294 }
295
296 void SamplingBar::on_sample_rate_changed()
297 {
298         commit_sample_rate();
299 }
300
301 void SamplingBar::on_configure()
302 {
303         commit_sample_rate();
304
305         sr_dev_inst *const sdi = get_selected_device();
306         assert(sdi);
307
308         pv::dialogs::DeviceOptions dlg(this, sdi);
309         dlg.exec();
310
311         update_sample_rate_selector_value();
312 }
313
314 void SamplingBar::on_run_stop()
315 {
316         commit_sample_rate();   
317         run_stop();
318 }
319
320 } // namespace toolbars
321 } // namespace pv