mirror of git://sigrok.org/pulseview
Added DeviceManager
This class now manages the application device list, scanning for devices, and releasing them when they are no longer needed. This fixes bug #108.
This commit is contained in:
parent
f9541bde55
commit
107ca6d350
|
@ -100,6 +100,7 @@ configure_file (
|
|||
|
||||
set(pulseview_SOURCES
|
||||
main.cpp
|
||||
pv/devicemanager.cpp
|
||||
pv/mainwindow.cpp
|
||||
pv/sigsession.cpp
|
||||
pv/data/analog.cpp
|
||||
|
|
20
main.cpp
20
main.cpp
|
@ -34,6 +34,7 @@
|
|||
#include "signalhandler.h"
|
||||
#endif
|
||||
|
||||
#include "pv/devicemanager.h"
|
||||
#include "pv/mainwindow.h"
|
||||
|
||||
#include "config.h"
|
||||
|
@ -128,20 +129,12 @@ int main(int argc, char *argv[])
|
|||
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
|
||||
|
@ -162,6 +155,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
// Run the application
|
||||
ret = a.exec();
|
||||
|
||||
} catch(std::exception e) {
|
||||
qDebug() << e.what();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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
|
|
@ -18,8 +18,12 @@
|
|||
* 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
|
||||
|
@ -27,13 +31,16 @@ extern "C" {
|
|||
#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),
|
||||
|
@ -148,11 +155,12 @@ void Connect::scan_pressed()
|
|||
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])
|
||||
|
@ -172,9 +180,6 @@ void Connect::scan_pressed()
|
|||
_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);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ struct sr_config;
|
|||
struct sr_dev_inst;
|
||||
|
||||
namespace pv {
|
||||
|
||||
class DeviceManager;
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
class Connect : public QDialog
|
||||
|
@ -41,7 +44,7 @@ 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;
|
||||
|
||||
|
@ -61,6 +64,8 @@ private:
|
|||
static void free_drvopts(sr_config *src);
|
||||
|
||||
private:
|
||||
pv::DeviceManager &_device_manager;
|
||||
|
||||
QVBoxLayout _layout;
|
||||
|
||||
QWidget _form;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
|
@ -36,6 +37,8 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "devicemanager.h"
|
||||
#include "dialogs/about.h"
|
||||
#include "dialogs/connect.h"
|
||||
#include "toolbars/samplingbar.h"
|
||||
|
@ -49,12 +52,15 @@
|
|||
#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) {
|
||||
|
@ -189,12 +195,7 @@ void MainWindow::setup_ui()
|
|||
_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()));
|
||||
|
@ -212,23 +213,6 @@ void MainWindow::setup_ui()
|
|||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -237,6 +221,30 @@ void MainWindow::session_error(
|
|||
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(
|
||||
|
@ -269,20 +277,12 @@ void MainWindow::on_actionOpen_triggered()
|
|||
|
||||
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()
|
||||
|
|
|
@ -37,6 +37,8 @@ class QWidget;
|
|||
|
||||
namespace pv {
|
||||
|
||||
class DeviceManager;
|
||||
|
||||
namespace toolbars {
|
||||
class SamplingBar;
|
||||
}
|
||||
|
@ -50,15 +52,24 @@ class MainWindow : public QMainWindow
|
|||
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);
|
||||
|
||||
|
@ -86,9 +97,9 @@ private slots:
|
|||
void capture_state_changed(int state);
|
||||
|
||||
private:
|
||||
DeviceManager &_device_manager;
|
||||
|
||||
SigSession _session;
|
||||
std::list<sr_dev_inst*> _devices;
|
||||
|
||||
pv::view::View *_view;
|
||||
|
||||
|
|
Loading…
Reference in New Issue