set(pulseview_SOURCES
main.cpp
+ pv/devicemanager.cpp
pv/mainwindow.cpp
pv/sigsession.cpp
pv/data/analog.cpp
#include "signalhandler.h"
#endif
+#include "pv/devicemanager.h"
#include "pv/mainwindow.h"
#include "config.h"
srd_decoder_load_all();
#endif
- // Initialize all libsigrok drivers
- sr_dev_driver **const drivers = sr_driver_list();
- for (sr_dev_driver **driver = drivers; *driver; driver++) {
- if (sr_driver_init(sr_ctx, *driver) != SR_OK) {
- qDebug("Failed to initialize driver %s",
- (*driver)->name);
- ret = 1;
- break;
- }
- }
+ try {
+ // Create the device manager, initialise the drivers
+ pv::DeviceManager device_manager(sr_ctx);
- if (ret == 0) {
// Initialise the main window
- pv::MainWindow w(open_file);
+ pv::MainWindow w(device_manager, open_file);
w.show();
#ifdef ENABLE_SIGNALS
// Run the application
ret = a.exec();
+
+ } catch(std::exception e) {
+ qDebug() << e.what();
}
#ifdef ENABLE_SIGROKDECODE
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "devicemanager.h"
+
+#include <cassert>
+#include <cstring>
+#include <stdexcept>
+#include <string>
+
+#include <libsigrok/libsigrok.h>
+
+using namespace std;
+
+namespace pv {
+
+DeviceManager::DeviceManager(struct sr_context *sr_ctx) :
+ _sr_ctx(sr_ctx)
+{
+ init_drivers();
+ scan_all_drivers();
+}
+
+DeviceManager::~DeviceManager()
+{
+ release_devices();
+}
+
+const std::list<sr_dev_inst*>& DeviceManager::devices() const
+{
+ return _devices;
+}
+
+list<sr_dev_inst*> DeviceManager::driver_scan(
+ struct sr_dev_driver *const driver, GSList *const drvopts)
+{
+ list<sr_dev_inst*> driver_devices;
+
+ assert(driver);
+
+ // Remove any device instances from this driver from the device
+ // list. They will not be valid after the scan.
+ list<sr_dev_inst*>::iterator i = _devices.begin();
+ while (i != _devices.end()) {
+ if ((*i)->driver == driver)
+ i = _devices.erase(i);
+ else
+ i++;
+ }
+
+ // Clear all the old device instances from this driver
+ sr_dev_clear(driver);
+
+ // Do the scan
+ GSList *const devices = sr_driver_scan(driver, drvopts);
+ for (GSList *l = devices; l; l = l->next)
+ driver_devices.push_back((sr_dev_inst*)l->data);
+ g_slist_free(devices);
+ driver_devices.sort(compare_devices);
+
+ // Add the scanned devices to the main list
+ _devices.insert(_devices.end(), driver_devices.begin(),
+ driver_devices.end());
+ _devices.sort(compare_devices);
+
+ return driver_devices;
+}
+
+void DeviceManager::init_drivers()
+{
+ // Initialise all libsigrok drivers
+ sr_dev_driver **const drivers = sr_driver_list();
+ for (sr_dev_driver **driver = drivers; *driver; driver++) {
+ if (sr_driver_init(_sr_ctx, *driver) != SR_OK) {
+ throw runtime_error(
+ string("Failed to initialize driver ") +
+ string((*driver)->name));
+ }
+ }
+}
+
+void DeviceManager::release_devices()
+{
+ sr_dev_driver **const drivers = sr_driver_list();
+ for (sr_dev_driver **driver = drivers; *driver; driver++)
+ sr_dev_clear(*driver);
+}
+
+void DeviceManager::scan_all_drivers()
+{
+ // Scan all drivers for all devices.
+ struct sr_dev_driver **const drivers = sr_driver_list();
+ for (struct sr_dev_driver **driver = drivers; *driver; driver++)
+ driver_scan(*driver);
+}
+
+bool DeviceManager::compare_devices(const sr_dev_inst *const a,
+ const sr_dev_inst *const b)
+{
+ assert(a);
+ assert(b);
+
+ const int vendor_cmp = strcasecmp(a->vendor, b->vendor);
+ if(vendor_cmp < 0)
+ return true;
+ else if(vendor_cmp > 0)
+ return false;
+
+ const int model_cmp = strcasecmp(a->model, b->model);
+ if(model_cmp < 0)
+ return true;
+ else if(model_cmp > 0)
+ return false;
+
+ return strcasecmp(a->version, b->version) < 0;
+}
+
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DEVICEMANAGER_H
+#define PULSEVIEW_PV_DEVICEMANAGER_H
+
+#include <glib.h>
+
+#include <list>
+
+struct sr_context;
+struct sr_dev_driver;
+struct sr_dev_inst;
+
+namespace pv {
+
+class DeviceManager
+{
+public:
+ DeviceManager(struct sr_context *sr_ctx);
+
+ ~DeviceManager();
+
+ const std::list<sr_dev_inst*>& devices() const;
+
+ std::list<sr_dev_inst*> driver_scan(
+ struct sr_dev_driver *const driver,
+ GSList *const drvopts = NULL);
+
+private:
+ void init_drivers();
+
+ static void release_devices();
+
+ void scan_all_drivers();
+
+ static bool compare_devices(const sr_dev_inst *const a,
+ const sr_dev_inst *const b);
+
+private:
+ struct sr_context *const _sr_ctx;
+ std::list<sr_dev_inst*> _devices;
+};
+
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DEVICEMANAGER_H
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <boost/foreach.hpp>
+
#include "connect.h"
+#include "pv/devicemanager.h"
+
extern "C" {
/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */
#define __STDC_FORMAT_MACROS
#include <libsigrok/libsigrok.h>
}
+using namespace std;
+
extern sr_context *sr_ctx;
namespace pv {
namespace dialogs {
-Connect::Connect(QWidget *parent) :
+Connect::Connect(QWidget *parent, pv::DeviceManager &device_manager) :
QDialog(parent),
+ _device_manager(device_manager),
_layout(this),
_form(this),
_form_layout(&_form),
drvopts = g_slist_append(drvopts, src);
}
- GSList *const devices = sr_driver_scan(driver, drvopts);
+ const list<sr_dev_inst*> devices = _device_manager.driver_scan(
+ driver, drvopts);
- for (GSList *l = devices; l; l = l->next) {
+ g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts);
- sr_dev_inst *const sdi = (sr_dev_inst*)l->data;
+ BOOST_FOREACH(sr_dev_inst *const sdi, devices) {
QString text;
if (sdi->vendor && sdi->vendor[0])
_device_list.addItem(item);
}
- g_slist_free(devices);
- g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts);
-
_device_list.setCurrentRow(0);
_button_box.button(QDialogButtonBox::Ok)->setDisabled(false);
}
struct sr_dev_inst;
namespace pv {
+
+class DeviceManager;
+
namespace dialogs {
class Connect : public QDialog
Q_OBJECT
public:
- Connect(QWidget *parent);
+ Connect(QWidget *parent, pv::DeviceManager &device_manager);
struct sr_dev_inst* get_selected_device() const;
static void free_drvopts(sr_config *src);
private:
+ pv::DeviceManager &_device_manager;
+
QVBoxLayout _layout;
QWidget _form;
#endif
#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
#include <QAction>
#include <QApplication>
#include <QWidget>
#include "mainwindow.h"
+
+#include "devicemanager.h"
#include "dialogs/about.h"
#include "dialogs/connect.h"
#include "toolbars/samplingbar.h"
#include <glib.h>
#include <libsigrok/libsigrok.h>
+using namespace std;
namespace pv {
-MainWindow::MainWindow(const char *open_file_name,
+MainWindow::MainWindow(DeviceManager &device_manager,
+ const char *open_file_name,
QWidget *parent) :
- QMainWindow(parent)
+ QMainWindow(parent),
+ _device_manager(device_manager)
{
setup_ui();
if (open_file_name) {
_sampling_bar = new toolbars::SamplingBar(this);
// Populate the device list and select the initially selected device
- scan_devices();
- if(!_devices.empty()) {
- struct sr_dev_inst *const initial_sdi = _devices.front();
- _sampling_bar->set_selected_device(initial_sdi);
- _session.set_device(initial_sdi);
- }
+ update_device_list();
connect(_sampling_bar, SIGNAL(device_selected()), this,
SLOT(device_selected()));
}
-void MainWindow::scan_devices()
-{
- _devices.clear();
-
- /* Scan all drivers for all devices. */
- struct sr_dev_driver **const drivers = sr_driver_list();
- for (struct sr_dev_driver **driver = drivers; *driver; driver++) {
- GSList *const devices = sr_driver_scan(*driver, NULL);
- for (GSList *l = devices; l; l = l->next)
- _devices.push_back((sr_dev_inst*)l->data);
- g_slist_free(devices);
- }
-
- assert(_sampling_bar);
- _sampling_bar->set_device_list(_devices);
-}
-
void MainWindow::session_error(
const QString text, const QString info_text)
{
Q_ARG(QString, info_text));
}
+void MainWindow::update_device_list(struct sr_dev_inst *selected_device)
+{
+ assert(_sampling_bar);
+
+ const list<sr_dev_inst*> &devices = _device_manager.devices();
+ _sampling_bar->set_device_list(devices);
+
+ if (!selected_device && !devices.empty()) {
+ // Fall back to the first device in the list.
+ selected_device = devices.front();
+
+ // Try and find the demo device and select that by default
+ BOOST_FOREACH (struct sr_dev_inst *sdi, devices)
+ if (strcmp(sdi->driver->name, "demo") == 0) {
+ selected_device = sdi;
+ }
+ }
+
+ if (selected_device) {
+ _sampling_bar->set_selected_device(selected_device);
+ _session.set_device(selected_device);
+ }
+}
+
void MainWindow::load_file(QString file_name)
{
const QString errorMessage(
void MainWindow::on_actionConnect_triggered()
{
- dialogs::Connect dlg(this);
+ dialogs::Connect dlg(this, _device_manager);
if (!dlg.exec())
return;
struct sr_dev_inst *const sdi = dlg.get_selected_device();
- if (sdi) {
- assert(_sampling_bar);
-
- _devices.push_back(sdi);
- _sampling_bar->set_device_list(_devices);
- _sampling_bar->set_selected_device(sdi);
-
- _session.set_device(sdi);
- }
+ update_device_list(sdi);
}
void MainWindow::on_actionQuit_triggered()
namespace pv {
+class DeviceManager;
+
namespace toolbars {
class SamplingBar;
}
Q_OBJECT
public:
- explicit MainWindow(const char *open_file_name = NULL,
+ explicit MainWindow(DeviceManager &device_manager,
+ const char *open_file_name = NULL,
QWidget *parent = 0);
private:
void setup_ui();
- void scan_devices();
void session_error(const QString text, const QString info_text);
+ /**
+ * Updates the device list in the sampling bar, and updates the
+ * selection.
+ * @param selected_device The device to select, or NULL if the
+ * first device in the device list should be selected.
+ */
+ void update_device_list(
+ struct sr_dev_inst *selected_device = NULL);
+
private slots:
void load_file(QString file_name);
void capture_state_changed(int state);
private:
+ DeviceManager &_device_manager;
SigSession _session;
- std::list<sr_dev_inst*> _devices;
pv::view::View *_view;