From: Joel Holdsworth Date: Sun, 22 Feb 2015 20:21:15 +0000 (+0000) Subject: Use device::Devices to represent sigrok Devices X-Git-Tag: pulseview-0.3.0~215 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=da30ecb7e72bd2547e524258efa5ec642988b70b;p=pulseview.git Use device::Devices to represent sigrok Devices --- diff --git a/CMakeLists.txt b/CMakeLists.txt index fdc5b69c..029f24b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,9 @@ set(pulseview_SOURCES pv/data/logicsegment.cpp pv/data/signaldata.cpp pv/data/segment.cpp + pv/devices/device.cpp + pv/devices/hardwaredevice.cpp + pv/devices/sessionfile.cpp pv/dialogs/about.cpp pv/dialogs/connect.cpp pv/dialogs/inputoutputoptions.cpp diff --git a/pv/devicemanager.cpp b/pv/devicemanager.cpp index 326cbca8..36d6fb6a 100644 --- a/pv/devicemanager.cpp +++ b/pv/devicemanager.cpp @@ -32,6 +32,8 @@ #include #include +#include + using boost::algorithm::join; using std::dynamic_pointer_cast; @@ -48,8 +50,6 @@ using Glib::VariantBase; using sigrok::ConfigKey; using sigrok::Context; using sigrok::Driver; -using sigrok::Device; -using sigrok::HardwareDevice; using sigrok::SessionDevice; namespace pv { @@ -75,80 +75,76 @@ shared_ptr DeviceManager::context() return context_; } -const list< shared_ptr >& DeviceManager::devices() const +const list< shared_ptr >& +DeviceManager::devices() const { return devices_; } -list< shared_ptr > DeviceManager::driver_scan( +list< shared_ptr > +DeviceManager::driver_scan( shared_ptr driver, map drvopts) { - list< shared_ptr > driver_devices; + list< shared_ptr > driver_devices; assert(driver); // Remove any device instances from this driver from the device // list. They will not be valid after the scan. - devices_.remove_if([&](shared_ptr device) { - return device->driver() == driver; }); + devices_.remove_if([&](shared_ptr device) { + return device->hardware_device()->driver() == driver; }); // Do the scan auto devices = driver->scan(drvopts); - driver_devices.insert(driver_devices.end(), devices.begin(), devices.end()); // Add the scanned devices to the main list, set display names and sort. - devices_.insert(devices_.end(), driver_devices.begin(), - driver_devices.end()); - - for (shared_ptr device : devices_) - build_display_name(device); - - devices_.sort([&](shared_ptr a, shared_ptr b) - { return compare_devices(a, b); }); + for (shared_ptr device : devices) { + const shared_ptr d( + new devices::HardwareDevice(context_, device)); + driver_devices.push_back(d); + } - // As the display names depend on the complete devices_ list, - // we need to recompute them. However, there is no need to - // recomute all names of the devices_ list since only the - // devices that use the given driver can be affected. - for (shared_ptr device : driver_devices) + for (shared_ptr device : driver_devices) build_display_name(device); - driver_devices.sort([&](shared_ptr a, shared_ptr b) + devices_.insert(devices_.end(), driver_devices.begin(), + driver_devices.end()); + devices_.sort([&](shared_ptr a, + shared_ptr b) { return compare_devices(a, b); }); return driver_devices; } const map DeviceManager::get_device_info( - shared_ptr device) + shared_ptr device) { map result; assert(device); - if (device->vendor().length() > 0) - result["vendor"] = device->vendor(); - if (device->model().length() > 0) - result["model"] = device->model(); - if (device->version().length() > 0) - result["version"] = device->version(); - if (device->serial_number().length() > 0) - result["serial_num"] = device->serial_number(); - if (device->connection_id().length() > 0) - result["connection_id"] = device->connection_id(); + const shared_ptr sr_dev = device->device(); + if (sr_dev->vendor().length() > 0) + result["vendor"] = sr_dev->vendor(); + if (sr_dev->model().length() > 0) + result["model"] = sr_dev->model(); + if (sr_dev->version().length() > 0) + result["version"] = sr_dev->version(); + if (sr_dev->serial_number().length() > 0) + result["serial_num"] = sr_dev->serial_number(); + if (sr_dev->connection_id().length() > 0) + result["connection_id"] = sr_dev->connection_id(); return result; } -const shared_ptr DeviceManager::find_device_from_info( +const shared_ptr DeviceManager::find_device_from_info( const map search_info) { - shared_ptr last_resort_dev; + shared_ptr last_resort_dev; map dev_info; - last_resort_dev = NULL; - - for (shared_ptr dev : devices_) { + for (shared_ptr dev : devices_) { assert(dev); dev_info = get_device_info(dev); @@ -191,10 +187,11 @@ const shared_ptr DeviceManager::find_device_from_info( return last_resort_dev; } -void DeviceManager::build_display_name(shared_ptr device) +void DeviceManager::build_display_name(shared_ptr device) { - auto session_device = dynamic_pointer_cast(device); - auto hardware_device = dynamic_pointer_cast(device); + const shared_ptr sr_dev = device->device(); + auto session_device = dynamic_pointer_cast(sr_dev); + auto hardware_device = dynamic_pointer_cast(sr_dev); if (session_device) { full_names_[device] = display_names_[device] = @@ -205,11 +202,11 @@ void DeviceManager::build_display_name(shared_ptr device) // First, build the device's full name. It always contains all // possible information. - vector parts = {device->vendor(), device->model(), - device->version(), device->serial_number()}; + vector parts = {sr_dev->vendor(), sr_dev->model(), + sr_dev->version(), sr_dev->serial_number()}; - if (device->connection_id().length() > 0) - parts.push_back("("+device->connection_id()+")"); + if (sr_dev->connection_id().length() > 0) + parts.push_back("("+sr_dev->connection_id()+")"); full_names_[device] = join(parts, " "); @@ -219,43 +216,46 @@ void DeviceManager::build_display_name(shared_ptr device) // we have at least two such devices and need to distinguish them. const bool multiple_dev = hardware_device && any_of( devices_.begin(), devices_.end(), - [&](shared_ptr dev) { - return (dev->vendor() == hardware_device->vendor() && - dev->model() == hardware_device->model()) && - dev != hardware_device; + [&](shared_ptr dev) { + return (dev->device()->vendor() == hardware_device->vendor() && + dev->device()->model() == hardware_device->model()) && + dev != device; } ); - parts = {device->vendor(), device->model()}; + parts = {sr_dev->vendor(), sr_dev->model()}; if (multiple_dev) { - parts.push_back(device->version()); - parts.push_back(device->serial_number()); + parts.push_back(sr_dev->version()); + parts.push_back(sr_dev->serial_number()); - if ((device->serial_number().length() == 0) && - (device->connection_id().length() > 0)) - parts.push_back("("+device->connection_id()+")"); + if ((sr_dev->serial_number().length() == 0) && + (sr_dev->connection_id().length() > 0)) + parts.push_back("("+sr_dev->connection_id()+")"); } display_names_[device] = join(parts, " "); } -const std::string DeviceManager::get_display_name(std::shared_ptr dev) +const std::string DeviceManager::get_display_name( + std::shared_ptr dev) { return display_names_[dev]; } -const std::string DeviceManager::get_full_name(std::shared_ptr dev) +const std::string DeviceManager::get_full_name( + std::shared_ptr dev) { return full_names_[dev]; } -void DeviceManager::update_display_name(std::shared_ptr dev) +void DeviceManager::update_display_name( + std::shared_ptr dev) { build_display_name(dev); } -bool DeviceManager::compare_devices(shared_ptr a, - shared_ptr b) +bool DeviceManager::compare_devices( + shared_ptr a, shared_ptr b) { assert(a); assert(b); diff --git a/pv/devicemanager.hpp b/pv/devicemanager.hpp index d6548ae1..8bceed34 100644 --- a/pv/devicemanager.hpp +++ b/pv/devicemanager.hpp @@ -34,12 +34,15 @@ namespace sigrok { class ConfigKey; class Context; class Driver; -class Device; -class HardwareDevice; } namespace pv { +namespace devices { +class Device; +class HardwareDevice; +} + class Session; class DeviceManager @@ -53,37 +56,38 @@ public: std::shared_ptr context(); - const std::list< std::shared_ptr >& + const std::list< std::shared_ptr >& devices() const; - std::list< std::shared_ptr > driver_scan( + std::list< std::shared_ptr > driver_scan( std::shared_ptr driver, std::map drvopts); const std::map get_device_info( - const std::shared_ptr device); + const std::shared_ptr device); - const std::shared_ptr find_device_from_info( + const std::shared_ptr find_device_from_info( const std::map search_info); - void build_display_name(std::shared_ptr device); + void build_display_name(std::shared_ptr device); - const std::string get_display_name(std::shared_ptr dev); + const std::string get_display_name( + std::shared_ptr dev); - const std::string get_full_name(std::shared_ptr dev); + const std::string get_full_name(std::shared_ptr dev); - void update_display_name(std::shared_ptr dev); + void update_display_name(std::shared_ptr dev); private: - bool compare_devices(std::shared_ptr a, - std::shared_ptr b); + bool compare_devices(std::shared_ptr a, + std::shared_ptr b); protected: std::shared_ptr context_; - std::list< std::shared_ptr > devices_; + std::list< std::shared_ptr > devices_; - std::map< std::shared_ptr, std::string > display_names_; - std::map< std::shared_ptr, std::string > full_names_; + std::map< std::shared_ptr, std::string > display_names_; + std::map< std::shared_ptr, std::string > full_names_; }; } // namespace pv diff --git a/pv/devices/device.cpp b/pv/devices/device.cpp new file mode 100644 index 00000000..004749c9 --- /dev/null +++ b/pv/devices/device.cpp @@ -0,0 +1,58 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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 + +#include + +#include "device.hpp" + +namespace pv { +namespace devices { + +Device::Device() { +} + +Device::~Device() { + if (session_) + session_->remove_datafeed_callbacks(); +} + +std::shared_ptr Device::session() const { + return session_; +} + +std::shared_ptr Device::device() const { + return device_; +} + +void Device::run() { + assert(device_); + assert(session_); + session_->run(); +} + +void Device::stop() { + assert(session_); + session_->stop(); +} + +} // namespace devices +} // namespace pv diff --git a/pv/devices/device.hpp b/pv/devices/device.hpp new file mode 100644 index 00000000..529fdd5b --- /dev/null +++ b/pv/devices/device.hpp @@ -0,0 +1,61 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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_DEVICES_DEVICE_HPP +#define PULSEVIEW_PV_DEVICES_DEVICE_HPP + +#include + + +namespace sigrok { +class Device; +class Session; +} // namespace sigrok + +namespace pv { +namespace devices { + +class Device +{ +protected: + Device(); + +public: + virtual ~Device(); + + std::shared_ptr session() const; + + std::shared_ptr device() const; + + virtual void create() = 0; + + virtual void run(); + + virtual void stop(); + +protected: + std::shared_ptr session_; + std::shared_ptr device_; +}; + +} // namespace devices +} // namespace pv + +#endif // PULSEVIEW_PV_DEVICES_DEVICE_HPP diff --git a/pv/devices/hardwaredevice.cpp b/pv/devices/hardwaredevice.cpp new file mode 100644 index 00000000..4fa27f6d --- /dev/null +++ b/pv/devices/hardwaredevice.cpp @@ -0,0 +1,63 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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 + +#include + +#include "hardwaredevice.hpp" + +using std::shared_ptr; +using std::static_pointer_cast; + +namespace pv { +namespace devices { + +HardwareDevice::HardwareDevice(const std::shared_ptr &context, + std::shared_ptr device) : + context_(context) { + device_ = device; +} + +HardwareDevice::~HardwareDevice() { + device_->close(); + if (session_) + session_->remove_devices(); +} + +shared_ptr HardwareDevice::hardware_device() const { + return static_pointer_cast(device_); +} + +void HardwareDevice::create() { + // Open the device + try { + device_->open(); + } catch(const sigrok::Error &e) { + throw QString(e.what()); + } + + // Set up the session + session_ = context_->create_session(); + session_->add_device(device_); +} + +} // namespace devices +} // namespace pv diff --git a/pv/devices/hardwaredevice.hpp b/pv/devices/hardwaredevice.hpp new file mode 100644 index 00000000..41d79068 --- /dev/null +++ b/pv/devices/hardwaredevice.hpp @@ -0,0 +1,53 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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_DEVICES_HARDWAREDEVICE_HPP +#define PULSEVIEW_PV_DEVICES_HARDWAREDEVICE_HPP + +#include "device.hpp" + +namespace sigrok { +class Context; +class HardwareDevice; +} // sigrok + +namespace pv { +namespace devices { + +class HardwareDevice final : public Device +{ +public: + HardwareDevice(const std::shared_ptr &context, + std::shared_ptr device); + + ~HardwareDevice(); + + std::shared_ptr hardware_device() const; + + void create(); + +private: + const std::shared_ptr context_; +}; + +} // namespace devices +} // namespace pv + +#endif // PULSEVIEW_PV_DEVICES_HARDWAREDEVICE_HPP diff --git a/pv/devices/sessionfile.cpp b/pv/devices/sessionfile.cpp new file mode 100644 index 00000000..4ca982ae --- /dev/null +++ b/pv/devices/sessionfile.cpp @@ -0,0 +1,40 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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 + +#include "sessionfile.hpp" + +namespace pv { +namespace devices { + +SessionFile::SessionFile(const std::shared_ptr &context, + const std::string &file_name) : + context_(context), + file_name_(file_name) { +} + +void SessionFile::create() { + session_ = context_->load_session(file_name_); + device_ = session_->devices()[0]; +} + +} // namespace devices +} // namespace pv diff --git a/pv/devices/sessionfile.hpp b/pv/devices/sessionfile.hpp new file mode 100644 index 00000000..0fcaa34c --- /dev/null +++ b/pv/devices/sessionfile.hpp @@ -0,0 +1,52 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Joel Holdsworth + * + * 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_DEVICES_SESSIONFILE_HPP +#define PULSEVIEW_PV_DEVICES_SESSIONFILE_HPP + +#include +#include + +#include "device.hpp" + +namespace sigrok { +class Context; +} // sigrok + +namespace pv { +namespace devices { + +class SessionFile final : public Device +{ +public: + SessionFile(const std::shared_ptr &context, + const std::string &file_name); + + void create(); + +private: + const std::shared_ptr &context_; + const std::string file_name_; +}; + +} // namespace devices +} // namespace pv + +#endif // PULSEVIEW_PV_DEVICES_SESSIONFILE_HPP diff --git a/pv/dialogs/connect.cpp b/pv/dialogs/connect.cpp index e5cc3dd7..20836901 100644 --- a/pv/dialogs/connect.cpp +++ b/pv/dialogs/connect.cpp @@ -24,7 +24,8 @@ #include "connect.hpp" -#include "pv/devicemanager.hpp" +#include +#include using std::list; using std::map; @@ -38,7 +39,8 @@ using Glib::VariantBase; using sigrok::ConfigKey; using sigrok::Driver; using sigrok::Error; -using sigrok::HardwareDevice; + +using pv::devices::HardwareDevice; namespace pv { namespace dialogs { @@ -167,7 +169,7 @@ void Connect::scan_pressed() serial.toUtf8().constData()); } - list< shared_ptr > devices = + const list< shared_ptr > devices = device_manager_.driver_scan(driver, drvopts); for (shared_ptr device : devices) @@ -176,7 +178,8 @@ void Connect::scan_pressed() QString text = QString::fromStdString( device_manager_.get_display_name(device)); - text += QString(" with %1 channels").arg(device->channels().size()); + text += QString(" with %1 channels").arg( + device->device()->channels().size()); QListWidgetItem *const item = new QListWidgetItem(text, &device_list_); diff --git a/pv/dialogs/connect.hpp b/pv/dialogs/connect.hpp index cc477631..a8f793ac 100644 --- a/pv/dialogs/connect.hpp +++ b/pv/dialogs/connect.hpp @@ -34,11 +34,16 @@ namespace sigrok { class Driver; +} + +namespace pv { +namespace devices { class HardwareDevice; } +} Q_DECLARE_METATYPE(std::shared_ptr); -Q_DECLARE_METATYPE(std::shared_ptr); +Q_DECLARE_METATYPE(std::shared_ptr); namespace pv { @@ -53,7 +58,7 @@ class Connect : public QDialog public: Connect(QWidget *parent, pv::DeviceManager &device_manager); - std::shared_ptr get_selected_device() const; + std::shared_ptr get_selected_device() const; private: void populate_drivers(); diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index f907f09c..b7a0818b 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -45,6 +45,8 @@ #include "mainwindow.hpp" #include "devicemanager.hpp" +#include "devices/hardwaredevice.hpp" +#include "devices/sessionfile.hpp" #include "dialogs/about.hpp" #include "dialogs/connect.hpp" #include "dialogs/inputoutputoptions.hpp" @@ -72,9 +74,7 @@ using std::vector; using boost::algorithm::join; -using sigrok::Device; using sigrok::Error; -using sigrok::HardwareDevice; using sigrok::OutputFormat; namespace pv { @@ -188,7 +188,7 @@ void MainWindow::run_stop() } } -void MainWindow::select_device(shared_ptr device) +void MainWindow::select_device(shared_ptr device) { try { session_.set_device(device); @@ -455,8 +455,6 @@ void MainWindow::restore_ui_settings() { QSettings settings; - shared_ptr device; - map dev_info; list key_list; string value; @@ -489,8 +487,8 @@ void MainWindow::restore_ui_settings() dev_info.insert(std::make_pair(key, value)); } - device = device_manager_.find_device_from_info(dev_info); - + const shared_ptr device = + device_manager_.find_device_from_info(dev_info); if (device) { select_device(device); update_device_list(); @@ -534,7 +532,10 @@ void MainWindow::load_file(QString file_name) const QString infoMessage; try { - session_.set_session_file(file_name.toStdString()); + session_.set_device( + shared_ptr(new devices::SessionFile( + device_manager_.context(), + file_name.toStdString()))); } catch(Error e) { show_session_error(tr("Failed to load ") + file_name, e.what()); session_.set_default_device(); @@ -658,7 +659,7 @@ void MainWindow::capture_state_changed(int state) void MainWindow::device_selected() { // Set the title to include the device/file name - const shared_ptr device = session_.device(); + const shared_ptr device = session_.device(); if (!device) return; diff --git a/pv/mainwindow.hpp b/pv/mainwindow.hpp index 2860c681..1779712f 100644 --- a/pv/mainwindow.hpp +++ b/pv/mainwindow.hpp @@ -33,7 +33,6 @@ struct srd_decoder; class QVBoxLayout; namespace sigrok { -class Device; class OutputFormat; } @@ -95,7 +94,7 @@ public: void run_stop(); - void select_device(std::shared_ptr device); + void select_device(std::shared_ptr device); public Q_SLOTS: void export_file(std::shared_ptr format); diff --git a/pv/popups/channels.cpp b/pv/popups/channels.cpp index 3d209e84..3ad494d3 100644 --- a/pv/popups/channels.cpp +++ b/pv/popups/channels.cpp @@ -28,6 +28,7 @@ #include "channels.hpp" #include +#include #include #include @@ -65,7 +66,7 @@ Channels::Channels(Session &session, QWidget *parent) : // Create the layout setLayout(&layout_); - shared_ptr device = session_.device(); + const shared_ptr device = session_.device()->device(); assert(device); // Collect a set of signals diff --git a/pv/session.cpp b/pv/session.cpp index 5f2bc8ea..27154d13 100644 --- a/pv/session.cpp +++ b/pv/session.cpp @@ -33,6 +33,9 @@ #include "data/logicsegment.hpp" #include "data/decode/decoder.hpp" +#include "devices/hardwaredevice.hpp" +#include "devices/sessionfile.hpp" + #include "view/analogsignal.hpp" #include "view/decodetrace.hpp" #include "view/logicsignal.hpp" @@ -68,9 +71,7 @@ using sigrok::Channel; using sigrok::ChannelType; using sigrok::ConfigKey; using sigrok::DatafeedCallbackFunction; -using sigrok::Device; using sigrok::Error; -using sigrok::HardwareDevice; using sigrok::Header; using sigrok::Logic; using sigrok::Meta; @@ -85,7 +86,6 @@ using Glib::Variant; namespace pv { Session::Session(DeviceManager &device_manager) : device_manager_(device_manager), - session_(device_manager.context()->create_session()), capture_state_(Stopped), cur_samplerate_(0) { @@ -108,91 +108,53 @@ const DeviceManager& Session::device_manager() const return device_manager_; } -const shared_ptr& Session::session() const +shared_ptr Session::session() const { - return session_; + if (!device_) + return shared_ptr(); + return device_->session(); } -shared_ptr Session::device() const +shared_ptr Session::device() const { return device_; } -void Session::set_device(shared_ptr device) +void Session::set_device(shared_ptr device) { + assert(device); + // Ensure we are not capturing before setting the device stop_capture(); - if (device_) { - session_->remove_datafeed_callbacks(); - - // Did we have a hardware device selected previously? - if (!dynamic_pointer_cast(device_)) { - device_->close(); - session_->remove_devices(); - } - } + device_ = std::move(device); + device_->create(); + device_->session()->add_datafeed_callback([=] + (shared_ptr device, shared_ptr packet) { + data_feed_in(device, packet); + }); + device_manager_.update_display_name(device_); + update_signals(device_); decode_traces_.clear(); - if (device) { - // Are we setting a session device? - const auto session_device = - dynamic_pointer_cast(device); - - if (session_device) - session_ = session_device->parent(); - else { - session_ = device_manager_.context()->create_session(); - - try { - device->open(); - } catch(const sigrok::Error &e) { - throw QString(e.what()); - } - - session_->add_device(device); - } - - device_ = device; - session_->add_datafeed_callback([=] - (shared_ptr device, shared_ptr packet) { - data_feed_in(device, packet); - }); - device_manager_.update_display_name(device); - update_signals(device); - } else - device_ = nullptr; - device_selected(); } -void Session::set_session_file(const string &name) -{ - const shared_ptr session = - device_manager_.context()->load_session(name); - set_device(session->devices()[0]); -} - void Session::set_default_device() { - shared_ptr default_device; - const list< shared_ptr > &devices = + const list< shared_ptr > &devices = device_manager_.devices(); - if (!devices.empty()) { - // Fall back to the first device in the list. - default_device = devices.front(); - - // Try and find the demo device and select that by default - for (shared_ptr dev : devices) - if (dev->driver()->name().compare("demo") == 0) { - default_device = dev; - break; - } + if (devices.empty()) + return; - set_device(default_device); - } + // Try and find the demo device and select that by default + const auto iter = std::find_if(devices.begin(), devices.end(), + [] (const shared_ptr &d) { + return d->hardware_device()->driver()->name() == + "demo"; }); + set_device((iter == devices.end()) ? devices.front() : *iter); } Session::capture_state Session::get_capture_state() const @@ -205,14 +167,11 @@ void Session::start_capture(function error_handler) { stop_capture(); - // Check that a device instance has been selected. - if (!device_) { - qDebug() << "No device selected"; - return; - } - // Check that at least one channel is enabled - auto channels = device_->channels(); + assert(device_); + const std::shared_ptr device = device_->device(); + assert(device); + auto channels = device->channels(); bool enabled = std::any_of(channels.begin(), channels.end(), [](shared_ptr channel) { return channel->enabled(); }); @@ -230,7 +189,7 @@ void Session::start_capture(function error_handler) void Session::stop_capture() { if (get_capture_state() != Stopped) - session_->stop(); + device_->stop(); // Check that sampling stopped if (sampling_thread_.joinable()) @@ -343,13 +302,13 @@ void Session::set_capture_state(capture_state state) capture_state_changed(state); } -void Session::update_signals(shared_ptr device) +void Session::update_signals(shared_ptr device) { assert(device); assert(capture_state_ == Stopped); // Detect what data types we will receive - auto channels = device->channels(); + auto channels = device->device()->channels(); unsigned int logic_channel_count = std::count_if( channels.begin(), channels.end(), [] (shared_ptr channel) { @@ -376,7 +335,7 @@ void Session::update_signals(shared_ptr device) unordered_set< shared_ptr > prev_sigs(signals_); signals_.clear(); - for (auto channel : device->channels()) { + for (auto channel : device->device()->channels()) { shared_ptr signal; // Find the channel in the old signals @@ -439,9 +398,10 @@ shared_ptr Session::signal_from_channel( return shared_ptr(); } -void Session::read_sample_rate(shared_ptr device) +void Session::read_sample_rate(shared_ptr device) { - const auto keys = device_->config_keys(ConfigKey::DEVICE_OPTIONS); + assert(device); + const auto keys = device->config_keys(ConfigKey::DEVICE_OPTIONS); const auto iter = keys.find(ConfigKey::SAMPLERATE); cur_samplerate_ = (iter != keys.end() && (*iter).second.find(sigrok::GET) != (*iter).second.end()) ? @@ -449,25 +409,27 @@ void Session::read_sample_rate(shared_ptr device) device->config_get(ConfigKey::SAMPLERATE)).get() : 0; } -void Session::sample_thread_proc(shared_ptr device, +void Session::sample_thread_proc(shared_ptr device, function error_handler) { assert(device); assert(error_handler); - read_sample_rate(device); + const std::shared_ptr sr_dev = device->device(); + assert(sr_dev); + read_sample_rate(sr_dev); try { - session_->start(); + device_->session()->start(); } catch(Error e) { error_handler(e.what()); return; } - set_capture_state(session_->trigger() ? + set_capture_state(device_->session()->trigger() ? AwaitingTrigger : Running); - session_->run(); + device_->run(); set_capture_state(Stopped); // Confirm that SR_DF_END was received @@ -478,16 +440,13 @@ void Session::sample_thread_proc(shared_ptr device, } } -void Session::feed_in_header(shared_ptr device) +void Session::feed_in_header() { - read_sample_rate(device); + read_sample_rate(device_->device()); } -void Session::feed_in_meta(shared_ptr device, - shared_ptr meta) +void Session::feed_in_meta(shared_ptr meta) { - (void)device; - for (auto entry : meta->config()) { switch (entry.first->id()) { case SR_CONF_SAMPLERATE: @@ -524,14 +483,18 @@ void Session::feed_in_logic(shared_ptr logic) set_capture_state(Running); // Get sample limit. - const auto keys = device_->config_keys( + assert(device_); + const std::shared_ptr device = + device_->device(); + assert(device); + const auto keys = device->config_keys( ConfigKey::DEVICE_OPTIONS); const auto iter = keys.find(ConfigKey::LIMIT_SAMPLES); const uint64_t sample_limit = (iter != keys.end() && (*iter).second.find(sigrok::GET) != (*iter).second.end()) ? VariantBase::cast_dynamic>( - device_->config_get(ConfigKey::LIMIT_SAMPLES)).get() : 0; + device->config_get(ConfigKey::LIMIT_SAMPLES)).get() : 0; // Create a new data segment cur_logic_segment_ = shared_ptr( @@ -583,8 +546,12 @@ void Session::feed_in_analog(shared_ptr analog) // Get sample limit. uint64_t sample_limit; try { + assert(device_); + const std::shared_ptr device = + device_->device(); + assert(device); sample_limit = VariantBase::cast_dynamic>( - device_->config_get(ConfigKey::LIMIT_SAMPLES)).get(); + device->config_get(ConfigKey::LIMIT_SAMPLES)).get(); } catch (Error) { sample_limit = 0; } @@ -623,18 +590,22 @@ void Session::feed_in_analog(shared_ptr analog) data_received(); } -void Session::data_feed_in(shared_ptr device, shared_ptr packet) +void Session::data_feed_in(shared_ptr device, + shared_ptr packet) { + (void)device; + assert(device); + assert(device == device_->device()); assert(packet); switch (packet->type()->id()) { case SR_DF_HEADER: - feed_in_header(device); + feed_in_header(); break; case SR_DF_META: - feed_in_meta(device, dynamic_pointer_cast(packet->payload())); + feed_in_meta(dynamic_pointer_cast(packet->payload())); break; case SR_DF_FRAME_BEGIN: diff --git a/pv/session.hpp b/pv/session.hpp index f5c87f69..69099b44 100644 --- a/pv/session.hpp +++ b/pv/session.hpp @@ -65,6 +65,10 @@ class LogicSegment; class SignalData; } +namespace devices { +class Device; +} + namespace view { class DecodeTrace; class LogicSignal; @@ -91,20 +95,14 @@ public: const DeviceManager& device_manager() const; - const std::shared_ptr& session() const; + std::shared_ptr session() const; - std::shared_ptr device() const; + std::shared_ptr device() const; /** * Sets device instance that will be used in the next capture session. */ - void set_device(std::shared_ptr device); - - /** - * Sets a sigrok session file as the capture device. - * @param name the path to the file. - */ - void set_session_file(const std::string &name); + void set_device(std::shared_ptr device); void set_default_device(); @@ -133,21 +131,20 @@ public: private: void set_capture_state(capture_state state); - void update_signals(std::shared_ptr device); + void update_signals(std::shared_ptr device); std::shared_ptr signal_from_channel( std::shared_ptr channel) const; - void read_sample_rate(std::shared_ptr); + void read_sample_rate(std::shared_ptr device); private: - void sample_thread_proc(std::shared_ptr device, + void sample_thread_proc(std::shared_ptr device, std::function error_handler); - void feed_in_header(std::shared_ptr device); + void feed_in_header(); - void feed_in_meta(std::shared_ptr device, - std::shared_ptr meta); + void feed_in_meta(std::shared_ptr meta); void feed_in_frame_begin(); @@ -160,12 +157,7 @@ private: private: DeviceManager &device_manager_; - std::shared_ptr session_; - - /** - * The device instance that will be used in the next capture session. - */ - std::shared_ptr device_; + std::shared_ptr device_; std::vector< std::shared_ptr > decode_traces_; diff --git a/pv/storesession.cpp b/pv/storesession.cpp index 1dad2d80..1a27e565 100644 --- a/pv/storesession.cpp +++ b/pv/storesession.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -132,7 +133,7 @@ bool StoreSession::start() // Begin storing try { const auto context = session_.device_manager().context(); - auto device = session_.device(); + auto device = session_.device()->device(); map options = options_; diff --git a/pv/toolbars/mainbar.cpp b/pv/toolbars/mainbar.cpp index adecf6ac..68f36ba3 100644 --- a/pv/toolbars/mainbar.cpp +++ b/pv/toolbars/mainbar.cpp @@ -32,6 +32,7 @@ #include "mainbar.hpp" #include +#include #include #include #include @@ -52,7 +53,6 @@ using std::vector; using sigrok::Capability; using sigrok::ConfigKey; -using sigrok::Device; using sigrok::Error; namespace pv { @@ -187,8 +187,8 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : void MainBar::update_device_list() { DeviceManager &mgr = session_.device_manager(); - shared_ptr selected_device = session_.device(); - list< shared_ptr > devs; + shared_ptr selected_device = session_.device(); + list< shared_ptr > devs; copy(mgr.devices().begin(), mgr.devices().end(), back_inserter(devs)); @@ -220,19 +220,21 @@ void MainBar::update_sample_rate_selector() if (updating_sample_rate_) return; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; assert(!updating_sample_rate_); updating_sample_rate_ = true; - const auto keys = device->config_keys(ConfigKey::DEVICE_OPTIONS); + const shared_ptr sr_dev = device->device(); + const auto keys = sr_dev->config_keys(ConfigKey::DEVICE_OPTIONS); const auto iter = keys.find(ConfigKey::SAMPLERATE); if (iter != keys.end() && (*iter).second.find(sigrok::LIST) != (*iter).second.end()) { try { - gvar_dict = device->config_list(ConfigKey::SAMPLERATE); + gvar_dict = sr_dev->config_list(ConfigKey::SAMPLERATE); } catch(const sigrok::Error &e) { // Failed to enunmerate samplerate (void)e; @@ -291,12 +293,13 @@ void MainBar::update_sample_rate_selector_value() if (updating_sample_rate_) return; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; try { - auto gvar = device->config_get(ConfigKey::SAMPLERATE); + auto gvar = device->device()->config_get(ConfigKey::SAMPLERATE); uint64_t samplerate = Glib::VariantBase::cast_dynamic>(gvar).get(); assert(!updating_sample_rate_); @@ -314,10 +317,13 @@ void MainBar::update_sample_count_selector() if (updating_sample_count_) return; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; + const shared_ptr sr_dev = device->device(); + assert(!updating_sample_count_); updating_sample_count_ = true; @@ -335,13 +341,13 @@ void MainBar::update_sample_count_selector() if (sample_count == 0) sample_count = DefaultSampleCount; - const auto keys = device->config_keys(ConfigKey::DEVICE_OPTIONS); + const auto keys = sr_dev->config_keys(ConfigKey::DEVICE_OPTIONS); const auto iter = keys.find(ConfigKey::LIMIT_SAMPLES); if (iter != keys.end() && (*iter).second.find(sigrok::LIST) != (*iter).second.end()) { try { auto gvar = - device->config_list(ConfigKey::LIMIT_SAMPLES); + sr_dev->config_list(ConfigKey::LIMIT_SAMPLES); if (gvar.gobj()) g_variant_get(gvar.gobj(), "(tt)", &min_sample_count, &max_sample_count); @@ -358,7 +364,7 @@ void MainBar::update_sample_count_selector() min_sample_count, max_sample_count); try { - auto gvar = device->config_get(ConfigKey::LIMIT_SAMPLES); + auto gvar = sr_dev->config_get(ConfigKey::LIMIT_SAMPLES); sample_count = g_variant_get_uint64(gvar.gobj()); if (sample_count == 0) sample_count = DefaultSampleCount; @@ -375,12 +381,17 @@ void MainBar::update_device_config_widgets() { using namespace pv::popups; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; + const shared_ptr sr_dev = device->device(); + if (!sr_dev) + return; + // Update the configure popup - DeviceOptions *const opts = new DeviceOptions(device, this); + DeviceOptions *const opts = new DeviceOptions(sr_dev, this); configure_button_action_->setVisible( !opts->binding().properties().empty()); configure_button_.set_popup(opts); @@ -393,7 +404,7 @@ void MainBar::update_device_config_widgets() sample_count_supported_ = false; try { - for (auto entry : device->config_keys(ConfigKey::DEVICE_OPTIONS)) + for (auto entry : sr_dev->config_keys(ConfigKey::DEVICE_OPTIONS)) { auto key = entry.first; auto capabilities = entry.second; @@ -405,7 +416,7 @@ void MainBar::update_device_config_widgets() case SR_CONF_LIMIT_FRAMES: if (capabilities.count(Capability::SET)) { - device->config_set(ConfigKey::LIMIT_FRAMES, + sr_dev->config_set(ConfigKey::LIMIT_FRAMES, Glib::Variant::create(1)); on_config_changed(); } @@ -433,10 +444,13 @@ void MainBar::commit_sample_count() if (updating_sample_count_) return; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; + const shared_ptr sr_dev = device->device(); + sample_count = sample_count_.value(); // Set the sample count @@ -445,7 +459,7 @@ void MainBar::commit_sample_count() if (sample_count_supported_) { try { - device->config_set(ConfigKey::LIMIT_SAMPLES, + sr_dev->config_set(ConfigKey::LIMIT_SAMPLES, Glib::Variant::create(sample_count)); on_config_changed(); } catch (Error error) { @@ -463,10 +477,13 @@ void MainBar::commit_sample_rate() if (updating_sample_rate_) return; - const shared_ptr device = device_selector_.selected_device(); + const shared_ptr device = + device_selector_.selected_device(); if (!device) return; + const shared_ptr sr_dev = device->device(); + sample_rate = sample_rate_.value(); if (sample_rate == 0) return; @@ -475,7 +492,7 @@ void MainBar::commit_sample_rate() assert(!updating_sample_rate_); updating_sample_rate_ = true; try { - device->config_set(ConfigKey::SAMPLERATE, + sr_dev->config_set(ConfigKey::SAMPLERATE, Glib::Variant::create(sample_rate)); on_config_changed(); } catch (Error error) { @@ -487,7 +504,7 @@ void MainBar::commit_sample_rate() void MainBar::on_device_selected() { - shared_ptr device = device_selector_.selected_device(); + shared_ptr device = device_selector_.selected_device(); if (!device) return; diff --git a/pv/view/logicsignal.cpp b/pv/view/logicsignal.cpp index 0d316961..58eaac93 100644 --- a/pv/view/logicsignal.cpp +++ b/pv/view/logicsignal.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,6 @@ using std::vector; using sigrok::Channel; using sigrok::ConfigKey; -using sigrok::Device; using sigrok::Error; using sigrok::Trigger; using sigrok::TriggerStage; @@ -99,7 +99,7 @@ QCache LogicSignal::pixmap_cache_; LogicSignal::LogicSignal( pv::Session &session, - shared_ptr device, + shared_ptr device, shared_ptr channel, shared_ptr data) : Signal(session, channel), @@ -321,13 +321,14 @@ void LogicSignal::init_trigger_actions(QWidget *parent) const vector LogicSignal::get_trigger_types() const { - const auto keys = device_->config_keys(ConfigKey::DEVICE_OPTIONS); + const auto sr_dev = device_->device(); + const auto keys = sr_dev->config_keys(ConfigKey::DEVICE_OPTIONS); const auto iter = keys.find(ConfigKey::TRIGGER_MATCH); if (iter != keys.end() && (*iter).second.find(sigrok::LIST) != (*iter).second.end()) { try { const Glib::VariantContainerBase gvar = - device_->config_list(ConfigKey::TRIGGER_MATCH); + sr_dev->config_list(ConfigKey::TRIGGER_MATCH); return Glib::VariantBase::cast_dynamic< Glib::Variant>>(gvar).get(); } catch (Error e) { diff --git a/pv/view/logicsignal.hpp b/pv/view/logicsignal.hpp index 7eb67dec..0705613e 100644 --- a/pv/view/logicsignal.hpp +++ b/pv/view/logicsignal.hpp @@ -31,12 +31,15 @@ class QIcon; class QToolBar; namespace sigrok { -class Device; class TriggerMatchType; } namespace pv { +namespace devices { +class Device; +} + namespace data { class Logic; } @@ -65,7 +68,7 @@ private: public: LogicSignal(pv::Session &session, - std::shared_ptr device, + std::shared_ptr device, std::shared_ptr channel, std::shared_ptr data); @@ -127,7 +130,7 @@ private Q_SLOTS: void on_trigger(); private: - std::shared_ptr device_; + std::shared_ptr device_; std::shared_ptr data_; const sigrok::TriggerMatchType *trigger_match_; diff --git a/pv/view/view.cpp b/pv/view/view.cpp index a05ac207..67d4f404 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -48,6 +48,7 @@ #include "viewport.hpp" #include "pv/session.hpp" +#include "pv/devices/device.hpp" #include "pv/data/logic.hpp" #include "pv/data/logicsegment.hpp" #include "pv/util.hpp" @@ -675,7 +676,7 @@ void View::signals_changed() // Populate the traces clear_child_items(); - shared_ptr device = session_.device(); + shared_ptr device = session_.device()->device(); assert(device); // Collect a set of signals diff --git a/pv/widgets/devicetoolbutton.cpp b/pv/widgets/devicetoolbutton.cpp index 9f1cc802..7ba8aa28 100644 --- a/pv/widgets/devicetoolbutton.cpp +++ b/pv/widgets/devicetoolbutton.cpp @@ -26,6 +26,7 @@ #include #include +#include #include "devicetoolbutton.hpp" @@ -35,7 +36,7 @@ using std::string; using std::weak_ptr; using std::vector; -using sigrok::Device; +using pv::devices::Device; namespace pv { namespace widgets { diff --git a/pv/widgets/devicetoolbutton.hpp b/pv/widgets/devicetoolbutton.hpp index af9e6e68..ed69a4b6 100644 --- a/pv/widgets/devicetoolbutton.hpp +++ b/pv/widgets/devicetoolbutton.hpp @@ -32,14 +32,14 @@ struct srd_decoder; -namespace sigrok { -class Device; -} - namespace pv { class DeviceManager; +namespace devices { +class Device; +} + namespace widgets { class DeviceToolButton : public QToolButton @@ -59,7 +59,7 @@ public: /** * Returns a reference to the selected device. */ - std::shared_ptr selected_device(); + std::shared_ptr selected_device(); /** * Sets the current list of devices. @@ -67,8 +67,8 @@ public: * @param selected_device the currently active device. */ void set_device_list( - const std::list< std::shared_ptr > &devices, - std::shared_ptr selected); + const std::list< std::shared_ptr > &devices, + std::shared_ptr selected); private: /** @@ -93,8 +93,8 @@ private: QMenu menu_; QSignalMapper mapper_; - std::shared_ptr selected_device_; - std::vector< std::weak_ptr > devices_; + std::shared_ptr selected_device_; + std::vector< std::weak_ptr > devices_; QString device_tooltip_; };