From: Martin Ling Date: Wed, 15 Oct 2014 00:04:55 +0000 (+0100) Subject: Use libsigrok C++ bindings (patch version 7). X-Git-Tag: pulseview-0.3.0~532 X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=e8d009288de28cb194bc7964f96677c2baf900c9 Use libsigrok C++ bindings (patch version 7). --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f334f911..31926adf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ endif() #= Dependencies #------------------------------------------------------------------------------- -list(APPEND PKGDEPS libsigrok>=0.3.0) +list(APPEND PKGDEPS libsigrokxx>=0.3.0) if(ENABLE_DECODE) list(APPEND PKGDEPS libsigrokdecode>=0.3.0) @@ -140,10 +140,6 @@ set(pulseview_SOURCES pv/data/logicsnapshot.cpp pv/data/signaldata.cpp pv/data/snapshot.cpp - pv/device/device.cpp - pv/device/file.cpp - pv/device/devinst.cpp - pv/device/sessionfile.cpp pv/dialogs/about.cpp pv/dialogs/connect.cpp pv/dialogs/storeprogress.cpp @@ -186,7 +182,6 @@ set(pulseview_HEADERS pv/mainwindow.h pv/sigsession.h pv/storesession.h - pv/device/devinst.h pv/dialogs/about.h pv/dialogs/connect.h pv/dialogs/storeprogress.h @@ -198,6 +193,7 @@ set(pulseview_HEADERS pv/prop/int.h pv/prop/property.h pv/prop/string.h + pv/prop/binding/deviceoptions.h pv/toolbars/samplingbar.h pv/view/cursor.h pv/view/cursorheader.h diff --git a/main.cpp b/main.cpp index 5c3e5b25..c0ac04b4 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,7 @@ #endif #include -#include +#include #include @@ -65,7 +65,7 @@ void usage() int main(int argc, char *argv[]) { int ret = 0; - struct sr_context *sr_ctx = NULL; + std::shared_ptr context; const char *open_file = NULL; Application a(argc, argv); @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) case 'l': { const int loglevel = atoi(optarg); - sr_log_loglevel_set(loglevel); + context->set_log_level(sigrok::LogLevel::get(loglevel)); #ifdef ENABLE_DECODE srd_log_loglevel_set(loglevel); @@ -121,10 +121,7 @@ int main(int argc, char *argv[]) open_file = argv[argc - 1]; // Initialise libsigrok - if (sr_init(&sr_ctx) != SR_OK) { - qDebug() << "ERROR: libsigrok init failed."; - return 1; - } + context = sigrok::Context::create(); do { @@ -141,7 +138,7 @@ int main(int argc, char *argv[]) try { // Create the device manager, initialise the drivers - pv::DeviceManager device_manager(sr_ctx); + pv::DeviceManager device_manager(context); // Initialise the main window pv::MainWindow w(device_manager, open_file); @@ -177,9 +174,5 @@ int main(int argc, char *argv[]) } while (0); - // Destroy libsigrok - if (sr_ctx) - sr_exit(sr_ctx); - return ret; } diff --git a/pv/data/decode/decoder.cpp b/pv/data/decode/decoder.cpp index 14097cfd..56ebc7e5 100644 --- a/pv/data/decode/decoder.cpp +++ b/pv/data/decode/decoder.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include #include "decoder.h" @@ -139,7 +139,7 @@ srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session, int unit_si { shared_ptr signal((*i).second); GVariant *const gvar = g_variant_new_int32( - signal->channel()->index); + signal->channel()->index()); g_variant_ref_sink(gvar); g_hash_table_insert(channels, (*i).first->id, gvar); } diff --git a/pv/data/logicsnapshot.cpp b/pv/data/logicsnapshot.cpp index 825d2f1f..a00a22ed 100644 --- a/pv/data/logicsnapshot.cpp +++ b/pv/data/logicsnapshot.cpp @@ -28,11 +28,16 @@ #include "config.h" #include "logicsnapshot.h" +#include + using std::lock_guard; using std::recursive_mutex; using std::max; using std::min; using std::pair; +using std::shared_ptr; + +using sigrok::Logic; namespace pv { namespace data { @@ -42,9 +47,9 @@ const int LogicSnapshot::MipMapScaleFactor = 1 << MipMapScalePower; const float LogicSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor); const uint64_t LogicSnapshot::MipMapDataUnit = 64*1024; // bytes -LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic, +LogicSnapshot::LogicSnapshot(shared_ptr logic, const uint64_t expected_num_samples) : - Snapshot(logic.unitsize), + Snapshot(logic->unit_size()), _last_append_sample(0) { set_capacity(expected_num_samples); @@ -135,15 +140,15 @@ void LogicSnapshot::pack_sample(uint8_t *ptr, uint64_t value) #endif } -void LogicSnapshot::append_payload( - const sr_datafeed_logic &logic) +void LogicSnapshot::append_payload(shared_ptr logic) { - assert(_unit_size == logic.unitsize); - assert((logic.length % _unit_size) == 0); + assert(_unit_size == logic->unit_size()); + assert((logic->data_length() % _unit_size) == 0); lock_guard lock(_mutex); - append_data(logic.data, logic.length / _unit_size); + append_data(logic->data_pointer(), + logic->data_length() / _unit_size); // Generate the first mip-map from the data append_payload_to_mipmap(); diff --git a/pv/data/logicsnapshot.h b/pv/data/logicsnapshot.h index bcb644da..a215f928 100644 --- a/pv/data/logicsnapshot.h +++ b/pv/data/logicsnapshot.h @@ -26,6 +26,10 @@ #include #include +namespace sigrok { + class Logic; +} + namespace LogicSnapshotTest { struct Pow2; struct Basic; @@ -58,12 +62,12 @@ public: typedef std::pair EdgePair; public: - LogicSnapshot(const sr_datafeed_logic &logic, + LogicSnapshot(std::shared_ptr logic, uint64_t expected_num_samples = 0); virtual ~LogicSnapshot(); - void append_payload(const sr_datafeed_logic &logic); + void append_payload(std::shared_ptr logic); void get_samples(uint8_t *const data, int64_t start_sample, int64_t end_sample) const; diff --git a/pv/data/snapshot.h b/pv/data/snapshot.h index fcb420c7..48879991 100644 --- a/pv/data/snapshot.h +++ b/pv/data/snapshot.h @@ -21,8 +21,6 @@ #ifndef PULSEVIEW_PV_DATA_SNAPSHOT_H #define PULSEVIEW_PV_DATA_SNAPSHOT_H -#include - #include #include #include diff --git a/pv/device/device.cpp b/pv/device/device.cpp deleted file mode 100644 index 546ce391..00000000 --- a/pv/device/device.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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 - -#include "device.h" - -using std::list; -using std::make_pair; -using std::map; -using std::ostringstream; -using std::string; - -namespace pv { -namespace device { - -Device::Device(sr_dev_inst *sdi) : - _sdi(sdi) -{ - assert(_sdi); -} - -sr_dev_inst* Device::dev_inst() const -{ - return _sdi; -} - -void Device::use(SigSession *owner) throw(QString) -{ - DevInst::use(owner); - - sr_session_new(&SigSession::_sr_session); - - assert(_sdi); - sr_dev_open(_sdi); - if (sr_session_dev_add(SigSession::_sr_session, _sdi) != SR_OK) - throw QString(tr("Failed to use device.")); -} - -void Device::release() -{ - if (_owner) { - DevInst::release(); - sr_session_destroy(SigSession::_sr_session); - } - - sr_dev_close(_sdi); -} - -std::string Device::format_device_title() const -{ - ostringstream s; - - assert(_sdi); - - if (_sdi->vendor && _sdi->vendor[0]) - s << _sdi->vendor << " "; - - if (_sdi->model && _sdi->model[0]) - s << _sdi->model << " "; - - if (_sdi->version && _sdi->version[0]) - s << _sdi->version << " "; - - // Show connection string only if no serial number is present. - if (_sdi->serial_num && _sdi->serial_num[0]) - s << "(" << _sdi->serial_num << ") "; - else if (_sdi->connection_id && _sdi->connection_id[0]) - s << "[" << _sdi->connection_id << "] "; - - // Remove trailing space. - s.seekp(-1, std::ios_base::end); - s << std::ends; - - return s.str(); -} - -map Device::get_device_info() const -{ - map result; - - assert(_sdi); - - if (_sdi->vendor && _sdi->vendor[0]) - result.insert(make_pair("vendor", _sdi->vendor)); - - if (_sdi->model && _sdi->model[0]) - result.insert(make_pair("model", _sdi->model)); - - if (_sdi->version && _sdi->version[0]) - result.insert(make_pair("version", _sdi->version)); - - if (_sdi->serial_num && _sdi->serial_num[0]) - result.insert(make_pair("serial_num", _sdi->serial_num)); - - if (_sdi->connection_id && _sdi->connection_id[0]) - result.insert(make_pair("connection_id", _sdi->connection_id)); - - return result; -} - -} // device -} // pv diff --git a/pv/device/device.h b/pv/device/device.h deleted file mode 100644 index 0a908a79..00000000 --- a/pv/device/device.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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_DEVICE_DEVICE_H -#define PULSEVIEW_PV_DEVICE_DEVICE_H - -#include -#include - -#include "devinst.h" - -namespace pv { -namespace device { - -class Device : public DevInst -{ -public: - Device(sr_dev_inst *dev_inst); - - sr_dev_inst* dev_inst() const; - - void use(SigSession *owner) throw(QString); - - void release(); - - std::string format_device_title() const; - - std::map get_device_info() const; - -private: - sr_dev_inst *const _sdi; -}; - -} // device -} // pv - -#endif // PULSVIEW_PV_DEVICE_DEVICE_H diff --git a/pv/device/devinst.cpp b/pv/device/devinst.cpp deleted file mode 100644 index 03010634..00000000 --- a/pv/device/devinst.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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 - -#include "devinst.h" - -#include - -namespace pv { -namespace device { - -DevInst::DevInst() : - _owner(NULL) -{ -} - -void DevInst::use(SigSession *owner) throw(QString) -{ - assert(owner); - assert(!_owner); - _owner = owner; -} - -void DevInst::release() -{ - if (_owner) { - _owner->release_device(this); - _owner = NULL; - } -} - -SigSession* DevInst::owner() const -{ - return _owner; -} - -GVariant* DevInst::get_config(const sr_channel_group *group, int key) -{ - GVariant *data = NULL; - assert(_owner); - sr_dev_inst *const sdi = dev_inst(); - assert(sdi); - if (sr_config_get(sdi->driver, sdi, group, key, &data) != SR_OK) - return NULL; - return data; -} - -bool DevInst::set_config(const sr_channel_group *group, int key, GVariant *data) -{ - assert(_owner); - sr_dev_inst *const sdi = dev_inst(); - assert(sdi); - if(sr_config_set(sdi, group, key, data) == SR_OK) { - config_changed(); - return true; - } - return false; -} - -GVariant* DevInst::list_config(const sr_channel_group *group, int key) -{ - GVariant *data = NULL; - assert(_owner); - sr_dev_inst *const sdi = dev_inst(); - assert(sdi); - if (sr_config_list(sdi->driver, sdi, group, key, &data) != SR_OK) - return NULL; - return data; -} - -void DevInst::enable_channel(const sr_channel *channel, bool enable) -{ - assert(_owner); - sr_dev_inst *const sdi = dev_inst(); - assert(sdi); - for (const GSList *p = sdi->channels; p; p = p->next) - if (channel == p->data) { - const_cast(channel)->enabled = enable; - config_changed(); - return; - } - - // Channel was not found in the device - assert(0); -} - -uint64_t DevInst::get_sample_limit() -{ - uint64_t sample_limit; - GVariant* gvar = get_config(NULL, SR_CONF_LIMIT_SAMPLES); - if (gvar != NULL) { - sample_limit = g_variant_get_uint64(gvar); - g_variant_unref(gvar); - } else { - sample_limit = 0U; - } - return sample_limit; -} - -bool DevInst::is_trigger_enabled() const -{ - return false; -} - -void DevInst::start() -{ - if (sr_session_start(SigSession::_sr_session) != SR_OK) - throw tr("Failed to start session."); -} - -void DevInst::run() -{ - sr_session_run(SigSession::_sr_session); -} - -} // device -} // pv diff --git a/pv/device/devinst.h b/pv/device/devinst.h deleted file mode 100644 index 1e0850c8..00000000 --- a/pv/device/devinst.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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_DEVICE_DEVINST_H -#define PULSEVIEW_PV_DEVICE_DEVINST_H - -#include -#include -#include - -#include - -#include - -#include - -struct sr_dev_inst; -struct sr_channel; -struct sr_channel_group; - -#include - -namespace pv { - -namespace device { - -class DevInst : public QObject -{ - Q_OBJECT - -protected: - DevInst(); - -public: - virtual sr_dev_inst* dev_inst() const = 0; - - virtual void use(SigSession *owner) throw(QString); - - virtual void release(); - - SigSession* owner() const; - - virtual std::string format_device_title() const = 0; - - virtual std::map get_device_info() const = 0; - - GVariant* get_config(const sr_channel_group *group, int key); - - bool set_config(const sr_channel_group *group, int key, GVariant *data); - - GVariant* list_config(const sr_channel_group *group, int key); - - void enable_channel(const sr_channel *channel, bool enable = true); - - /** - * @brief Gets the sample limit from the driver. - * - * @return The returned sample limit from the driver, or 0 if the - * sample limit could not be read. - */ - uint64_t get_sample_limit(); - - virtual bool is_trigger_enabled() const; - -public: - virtual void start(); - - virtual void run(); - -Q_SIGNALS: - void config_changed(); - -protected: - SigSession *_owner; -}; - -} // device -} // pv - -#endif // PULSEVIEW_PV_DEVICE_DEVINST_H diff --git a/pv/device/file.cpp b/pv/device/file.cpp deleted file mode 100644 index 368276a4..00000000 --- a/pv/device/file.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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 "file.h" -#include "sessionfile.h" - -#include - -#include - -using std::make_pair; -using std::map; -using std::string; - -namespace pv { -namespace device { - -File::File(const std::string path) : - _path(path) -{ -} - -std::string File::format_device_title() const -{ - return boost::filesystem::path(_path).filename().string(); -} - -map File::get_device_info() const -{ - map result; - - result.insert(make_pair("vendor", "sigrok")); - result.insert(make_pair("model", "file")); - result.insert(make_pair("connection_id", - boost::filesystem::path(_path).filename().string())); - - return result; -} - -File* File::create(const string &name) -{ - struct sr_session *temp_session; - if (sr_session_load(name.c_str(), &temp_session) == SR_OK) { - GSList *devlist = NULL; - sr_session_dev_list(temp_session, &devlist); - sr_session_destroy(temp_session); - - if (devlist) { - sr_dev_inst *const sdi = (sr_dev_inst*)devlist->data; - g_slist_free(devlist); - if (sdi) { - sr_dev_close(sdi); - sr_dev_clear(sdi->driver); - return new SessionFile(name); - } - } - } - - return NULL; -} - -} // device -} // pv diff --git a/pv/device/file.h b/pv/device/file.h deleted file mode 100644 index c6c21cac..00000000 --- a/pv/device/file.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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_DEVICE_FILE_H -#define PULSEVIEW_PV_DEVICE_FILE_H - -#include - -#include "devinst.h" - -namespace pv { -namespace device { - -class File : public DevInst -{ -protected: - File(const std::string path); - -public: - static File* create(const std::string &name); - -public: - std::string format_device_title() const; - - std::map get_device_info() const; - -protected: - const std::string _path; -}; - -} // device -} // pv - -#endif // PULSEVIEW_PV_DEVICE_FILE_H diff --git a/pv/device/sessionfile.cpp b/pv/device/sessionfile.cpp deleted file mode 100644 index a2810d42..00000000 --- a/pv/device/sessionfile.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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.h" - -#include - -namespace pv { -namespace device { - -SessionFile::SessionFile(const std::string &path) : - File(path), - _sdi(NULL) -{ -} - -sr_dev_inst* SessionFile::dev_inst() const -{ - return _sdi; -} - -void SessionFile::use(SigSession *owner) throw(QString) -{ - assert(!_sdi); - - if (sr_session_load(_path.c_str(), &SigSession::_sr_session) != SR_OK) - throw tr("Failed to open file.\n"); - - GSList *devlist = NULL; - sr_session_dev_list(SigSession::_sr_session, &devlist); - - if (!devlist || !devlist->data) { - if (devlist) - g_slist_free(devlist); - throw tr("Failed to start session."); - } - - _sdi = (sr_dev_inst*)devlist->data; - g_slist_free(devlist); - - File::use(owner); -} - -void SessionFile::release() -{ - if (!_owner) - return; - - assert(_sdi); - File::release(); - sr_dev_close(_sdi); - sr_dev_clear(_sdi->driver); - sr_session_destroy(SigSession::_sr_session); - _sdi = NULL; -} - -} // device -} // pv diff --git a/pv/device/sessionfile.h b/pv/device/sessionfile.h deleted file mode 100644 index c0ed958c..00000000 --- a/pv/device/sessionfile.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the PulseView project. - * - * Copyright (C) 2014 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_DEVICE_SESSIONFILE_H -#define PULSEVIEW_PV_DEVICE_SESSIONFILE_H - -#include "file.h" - -namespace pv { -namespace device { - -class SessionFile : public File -{ -public: - SessionFile(const std::string &path); - - sr_dev_inst* dev_inst() const; - - virtual void use(SigSession *owner) throw(QString); - - virtual void release(); - -private: - sr_dev_inst *_sdi; -}; - -} // device -} // pv - -#endif // PULSEVIEW_PV_DEVICE_SESSIONFILE_H diff --git a/pv/devicemanager.cpp b/pv/devicemanager.cpp index 13b44e96..c06fd79f 100644 --- a/pv/devicemanager.cpp +++ b/pv/devicemanager.cpp @@ -19,66 +19,76 @@ */ #include "devicemanager.h" -#include "device/device.h" #include "sigsession.h" #include #include +#include #include +#include -#include +#include +#include + +using std::dynamic_pointer_cast; using std::list; using std::map; +using std::ostringstream; +using std::remove_if; using std::runtime_error; using std::shared_ptr; using std::string; +using std::vector; + +using Glib::VariantBase; + +using sigrok::ConfigKey; +using sigrok::Context; +using sigrok::Driver; +using sigrok::Device; +using sigrok::HardwareDevice; +using sigrok::SessionDevice; namespace pv { -DeviceManager::DeviceManager(struct sr_context *sr_ctx) : - _sr_ctx(sr_ctx) +DeviceManager::DeviceManager(shared_ptr context) : + _context(context) { - init_drivers(); - scan_all_drivers(); + for (auto entry : context->drivers()) + driver_scan(entry.second, map()); } DeviceManager::~DeviceManager() { - release_devices(); } -const list< shared_ptr >& DeviceManager::devices() const +shared_ptr DeviceManager::context() +{ + return _context; +} + +const list< shared_ptr >& DeviceManager::devices() const { return _devices; } -list< shared_ptr > DeviceManager::driver_scan( - struct sr_dev_driver *const driver, GSList *const drvopts) +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. - auto i = _devices.begin(); - while (i != _devices.end()) { - if ((*i)->dev_inst()->driver == driver) - i = _devices.erase(i); - else - i++; - } - - // Release this driver and all it's attached devices - release_driver(driver); + remove_if(_devices.begin(), _devices.end(), + [&](shared_ptr device) { + return device->driver() == driver; }); // Do the scan - GSList *const devices = sr_driver_scan(driver, drvopts); - for (GSList *l = devices; l; l = l->next) - driver_devices.push_back(shared_ptr( - new device::Device((sr_dev_inst*)l->data))); - g_slist_free(devices); + auto devices = driver->scan(drvopts); + driver_devices.insert(driver_devices.end(), devices.begin(), devices.end()); driver_devices.sort(compare_devices); // Add the scanned devices to the main list @@ -89,17 +99,38 @@ list< shared_ptr > DeviceManager::driver_scan( return driver_devices; } -const shared_ptr DeviceManager::find_device_from_info( +const map DeviceManager::get_device_info( + 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(); + + return result; +} + +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 = dev->get_device_info(); + dev_info = get_device_info(dev); // If present, vendor and model always have to match. if (dev_info.count("vendor") > 0 && search_info.count("vendor") > 0) @@ -140,59 +171,43 @@ const shared_ptr DeviceManager::find_device_from_info( return last_resort_dev; } -void DeviceManager::init_drivers() +string DeviceManager::device_description(shared_ptr device) { - // 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)); - } - } -} + auto session_device = dynamic_pointer_cast(device); -void DeviceManager::release_devices() -{ - // Release all the used devices - for (shared_ptr dev : _devices) { - assert(dev); - dev->release(); - } + if (session_device) + return boost::filesystem::path( + session_device->parent()->filename()).filename().string(); - // Clear all the drivers - sr_dev_driver **const drivers = sr_driver_list(); - for (sr_dev_driver **driver = drivers; *driver; driver++) - sr_dev_clear(*driver); -} + ostringstream s; -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); -} + vector parts = {device->vendor(), device->model(), + device->version(), device->serial_number()}; -void DeviceManager::release_driver(struct sr_dev_driver *const driver) -{ - for (shared_ptr dev : _devices) { - assert(dev); - if(dev->dev_inst()->driver == driver) - dev->release(); + for (size_t i = 0; i < parts.size(); i++) + { + if (parts[i].length() > 0) + { + if (i != 0) + s << " "; + s << parts[i]; + } } - // Clear all the old device instances from this driver - sr_dev_clear(driver); + if (device->serial_number().length() == 0 && + device->connection_id().length() > 0) + s << " " << device->connection_id(); + + return s.str(); } -bool DeviceManager::compare_devices(shared_ptr a, - shared_ptr b) +bool DeviceManager::compare_devices(shared_ptr a, + shared_ptr b) { assert(a); assert(b); - return a->format_device_title().compare(b->format_device_title()) < 0; + + return device_description(a).compare(device_description(b)) < 0; } } // namespace pv diff --git a/pv/devicemanager.h b/pv/devicemanager.h index 0a8f2e0d..0a47a35a 100644 --- a/pv/devicemanager.h +++ b/pv/devicemanager.h @@ -21,56 +21,58 @@ #ifndef PULSEVIEW_PV_DEVICEMANAGER_H #define PULSEVIEW_PV_DEVICEMANAGER_H -#include - #include #include #include #include -struct sr_context; -struct sr_dev_driver; +namespace Glib { + class VariantBase; +} + +namespace sigrok { + class ConfigKey; + class Context; + class Driver; + class Device; + class HardwareDevice; +} namespace pv { class SigSession; -namespace device { -class Device; -} - class DeviceManager { public: - DeviceManager(struct sr_context *sr_ctx); + DeviceManager(std::shared_ptr context); ~DeviceManager(); - const std::list< std::shared_ptr >& - devices() const; - - std::list< std::shared_ptr > driver_scan( - struct sr_dev_driver *const driver, - GSList *const drvopts = NULL); - - const std::shared_ptr find_device_from_info( - const std::map search_info); + std::shared_ptr context(); -private: - void init_drivers(); + const std::list< std::shared_ptr >& + devices() const; - void release_devices(); + std::list< std::shared_ptr > driver_scan( + std::shared_ptr driver, + std::map drvopts); - void scan_all_drivers(); + const std::map get_device_info( + const std::shared_ptr device); - void release_driver(struct sr_dev_driver *const driver); + const std::shared_ptr find_device_from_info( + const std::map search_info); - static bool compare_devices(std::shared_ptr a, - std::shared_ptr b); + static std::string device_description(std::shared_ptr device); private: - struct sr_context *const _sr_ctx; - std::list< std::shared_ptr > _devices; + static bool compare_devices(std::shared_ptr a, + std::shared_ptr b); + +protected: + std::shared_ptr _context; + std::list< std::shared_ptr > _devices; }; } // namespace pv diff --git a/pv/dialogs/about.cpp b/pv/dialogs/about.cpp index f8394f2a..05daff8a 100644 --- a/pv/dialogs/about.cpp +++ b/pv/dialogs/about.cpp @@ -27,21 +27,18 @@ #include "about.h" #include -/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */ -#define __STDC_FORMAT_MACROS -#include -#include +#include +using std::shared_ptr; +using sigrok::Context; namespace pv { namespace dialogs { -About::About(QWidget *parent) : +About::About(shared_ptr context, QWidget *parent) : QDialog(parent), ui(new Ui::About) { - struct sr_dev_driver **drivers; - #ifdef ENABLE_DECODE struct srd_decoder *dec; #endif @@ -64,11 +61,19 @@ About::About(QWidget *parent) : s.append("" + tr("Supported hardware drivers:") + ""); - drivers = sr_driver_list(); - for (int i = 0; drivers[i]; ++i) { + for (auto entry : context->drivers()) { + s.append(QString("%1%2") + .arg(QString::fromUtf8(entry.first.c_str())) + .arg(QString::fromUtf8(entry.second->long_name().c_str()))); + } + + s.append("" + + tr("Supported input formats:") + + ""); + for (auto entry : context->input_formats()) { s.append(QString("%1%2") - .arg(QString::fromUtf8(drivers[i]->name)) - .arg(QString::fromUtf8(drivers[i]->longname))); + .arg(QString::fromUtf8(entry.first.c_str())) + .arg(QString::fromUtf8(entry.second->description().c_str()))); } #ifdef ENABLE_DECODE diff --git a/pv/dialogs/about.h b/pv/dialogs/about.h index cc153add..6656f9c0 100644 --- a/pv/dialogs/about.h +++ b/pv/dialogs/about.h @@ -27,6 +27,10 @@ class QTextDocument; +namespace sigrok { + class Context; +} + namespace Ui { class About; } @@ -39,7 +43,7 @@ class About : public QDialog Q_OBJECT public: - explicit About(QWidget *parent = 0); + explicit About(std::shared_ptr context, QWidget *parent = 0); ~About(); private: diff --git a/pv/dialogs/connect.cpp b/pv/dialogs/connect.cpp index 1156d6f5..19dfde8d 100644 --- a/pv/dialogs/connect.cpp +++ b/pv/dialogs/connect.cpp @@ -20,25 +20,25 @@ #include -#include +#include #include "connect.h" #include "pv/devicemanager.h" -#include "pv/device/device.h" - -extern "C" { -/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */ -#define __STDC_FORMAT_MACROS -#include -#include -} using std::list; +using std::map; using std::shared_ptr; using std::string; -extern sr_context *sr_ctx; +using Glib::ustring; +using Glib::Variant; +using Glib::VariantBase; + +using sigrok::ConfigKey; +using sigrok::Driver; +using sigrok::Error; +using sigrok::HardwareDevice; namespace pv { namespace dialogs { @@ -82,30 +82,20 @@ Connect::Connect(QWidget *parent, pv::DeviceManager &device_manager) : _layout.addWidget(&_button_box); } -shared_ptr Connect::get_selected_device() const +shared_ptr Connect::get_selected_device() const { const QListWidgetItem *const item = _device_list.currentItem(); if (!item) - return shared_ptr(); - - const sr_dev_inst *const sdi = (sr_dev_inst*)item->data( - Qt::UserRole).value(); - assert(sdi); - - const auto iter = _device_map.find(sdi); - assert(iter != _device_map.end()); + return shared_ptr(); - return (*iter).second; + return item->data(Qt::UserRole).value>(); } void Connect::populate_drivers() { - gsize num_opts = 0; - const int32_t *hwopts; - struct sr_dev_driver **drivers = sr_driver_list(); - GVariant *gvar_opts; - - for (int i = 0; drivers[i]; ++i) { + for (auto entry : _device_manager.context()->drivers()) { + auto name = entry.first; + auto driver = entry.second; /** * We currently only support devices that can deliver * samples at a fixed samplerate i.e. oscilloscopes and @@ -113,29 +103,19 @@ void Connect::populate_drivers() * @todo Add support for non-monotonic devices i.e. DMMs * and sensors. */ - bool supported_device = false; - if ((sr_config_list(drivers[i], NULL, NULL, - SR_CONF_DEVICE_OPTIONS, &gvar_opts) == SR_OK)) { - hwopts = (const int32_t *)g_variant_get_fixed_array(gvar_opts, - &num_opts, sizeof(int32_t)); - for (unsigned int j = 0; j < num_opts; j++) - if ((hwopts[j] & SR_CONF_MASK) == SR_CONF_SAMPLERATE) { - supported_device = true; - break; - } - } + bool supported_device = driver->config_check( + ConfigKey::SAMPLERATE, ConfigKey::DEVICE_OPTIONS); if (supported_device) _drivers.addItem(QString("%1 (%2)").arg( - drivers[i]->longname).arg(drivers[i]->name), - qVariantFromValue((void*)drivers[i])); + driver->long_name().c_str()).arg(name.c_str()), + qVariantFromValue(driver)); } } void Connect::unset_connection() { _device_list.clear(); - _device_map.clear(); _serial_device.hide(); _form_layout.labelForField(&_serial_device)->hide(); _button_box.button(QDialogButtonBox::Ok)->setDisabled(true); @@ -150,49 +130,37 @@ void Connect::set_serial_connection() void Connect::scan_pressed() { _device_list.clear(); - _device_map.clear(); const int index = _drivers.currentIndex(); if (index == -1) return; - sr_dev_driver *const driver = (sr_dev_driver*)_drivers.itemData( - index).value(); + shared_ptr driver = + _drivers.itemData(index).value>(); - GSList *drvopts = NULL; + assert(driver); - if (_serial_device.isVisible()) { - sr_config *const src = (sr_config*)g_try_malloc(sizeof(sr_config)); - src->key = SR_CONF_CONN; - const QByteArray byteArray = _serial_device.text().toUtf8(); - src->data = g_variant_new_string((const gchar*)byteArray.constData()); - drvopts = g_slist_append(drvopts, src); - } + map drvopts; - const list< shared_ptr > devices = - _device_manager.driver_scan(driver, drvopts); + if (_serial_device.isVisible()) + drvopts[ConfigKey::CONN] = Variant::create( + _serial_device.text().toUtf8().constData()); - g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts); + list< shared_ptr > devices = + _device_manager.driver_scan(driver, drvopts); - for (shared_ptr dev_inst : devices) + for (shared_ptr device : devices) { - assert(dev_inst); - const sr_dev_inst *const sdi = dev_inst->dev_inst(); - assert(sdi); + assert(device); - const string title = dev_inst->format_device_title(); - QString text = QString::fromUtf8(title.c_str()); - - if (sdi->channels) { - text += QString(" with %1 channels").arg( - g_slist_length(sdi->channels)); - } + QString text = QString::fromStdString( + _device_manager.device_description(device)); + text += QString(" with %1 channels").arg(device->channels().size()); QListWidgetItem *const item = new QListWidgetItem(text, &_device_list); - item->setData(Qt::UserRole, qVariantFromValue((void*)sdi)); + item->setData(Qt::UserRole, qVariantFromValue(device)); _device_list.addItem(item); - _device_map[sdi] = dev_inst; } _device_list.setCurrentRow(0); @@ -201,39 +169,13 @@ void Connect::scan_pressed() void Connect::device_selected(int index) { - gsize num_opts = 0; - const int32_t *hwopts; - GVariant *gvar_list; - sr_dev_driver *const driver = (sr_dev_driver*)_drivers.itemData( - index).value(); + shared_ptr driver = + _drivers.itemData(index).value>(); unset_connection(); - if ((sr_config_list(driver, NULL, NULL, - SR_CONF_SCAN_OPTIONS, &gvar_list) == SR_OK)) { - hwopts = (const int32_t *)g_variant_get_fixed_array(gvar_list, - &num_opts, sizeof(int32_t)); - - for (unsigned int i = 0; i < num_opts; i++) { - switch(hwopts[i]) { - case SR_CONF_SERIALCOMM: - set_serial_connection(); - break; - - default: - continue; - } - - break; - } - g_variant_unref(gvar_list); - } -} - -void Connect::free_drvopts(struct sr_config *src) -{ - g_variant_unref(src->data); - g_free(src); + if (driver->config_check(ConfigKey::SERIALCOMM, ConfigKey::SCAN_OPTIONS)) + set_serial_connection(); } } // namespace dialogs diff --git a/pv/dialogs/connect.h b/pv/dialogs/connect.h index e1a2c30d..fbac9e3e 100644 --- a/pv/dialogs/connect.h +++ b/pv/dialogs/connect.h @@ -32,17 +32,18 @@ #include #include -struct sr_config; -struct sr_dev_inst; +namespace sigrok { + class Driver; + class HardwareDevice; +} + +Q_DECLARE_METATYPE(std::shared_ptr); +Q_DECLARE_METATYPE(std::shared_ptr); namespace pv { class DeviceManager; -namespace device { -class Device; -} - namespace dialogs { class Connect : public QDialog @@ -52,7 +53,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(); @@ -66,9 +67,6 @@ private Q_SLOTS: void scan_pressed(); -private: - static void free_drvopts(sr_config *src); - private: pv::DeviceManager &_device_manager; @@ -83,8 +81,6 @@ private: QPushButton _scan_button; QListWidget _device_list; - std::map > - _device_map; QDialogButtonBox _button_box; }; diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index d4c5f1f7..598976eb 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -43,7 +43,6 @@ #include "mainwindow.h" #include "devicemanager.h" -#include "device/device.h" #include "dialogs/about.h" #include "dialogs/connect.h" #include "dialogs/storeprogress.h" @@ -54,19 +53,21 @@ #include "widgets/decodermenu.h" #endif -/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */ -#define __STDC_FORMAT_MACROS #include #include #include #include -#include +#include using std::list; using std::map; using std::shared_ptr; using std::string; +using sigrok::Device; +using sigrok::Error; +using sigrok::HardwareDevice; + namespace pv { namespace view { @@ -290,7 +291,8 @@ void MainWindow::save_ui_settings() key_list.push_back("serial_num"); key_list.push_back("connection_id"); - dev_info = _session.get_device()->get_device_info(); + dev_info = _device_manager.get_device_info( + _session.get_device()); for (string key : key_list) { @@ -309,7 +311,7 @@ void MainWindow::restore_ui_settings() { QSettings settings; - shared_ptr device; + shared_ptr device; map dev_info; list key_list; @@ -365,8 +367,8 @@ void MainWindow::update_device_list() { assert(_sampling_bar); - shared_ptr selected_device = _session.get_device(); - list< shared_ptr > devices; + shared_ptr selected_device = _session.get_device(); + list< shared_ptr > devices; if (_device_manager.devices().size() == 0) return; @@ -379,7 +381,12 @@ void MainWindow::update_device_list() devices.push_back(selected_device); assert(selected_device); - _sampling_bar->set_device_list(devices, selected_device); + map, string> device_names; + + for (auto device : devices) + device_names[device] = _device_manager.device_description(device); + + _sampling_bar->set_device_list(device_names, selected_device); } void MainWindow::closeEvent(QCloseEvent *event) @@ -396,8 +403,8 @@ void MainWindow::load_file(QString file_name) try { _session.set_file(file_name.toStdString()); - } catch(QString e) { - show_session_error(tr("Failed to load ") + file_name, e); + } catch(Error e) { + show_session_error(tr("Failed to load ") + file_name, e.what()); _session.set_default_device(); update_device_list(); return; @@ -516,7 +523,7 @@ void MainWindow::on_actionViewShowCursors_triggered() void MainWindow::on_actionAbout_triggered() { - dialogs::About dlg(this); + dialogs::About dlg(_device_manager.context(), this); dlg.exec(); } diff --git a/pv/mainwindow.h b/pv/mainwindow.h index 1b2135df..b9fc3e0e 100644 --- a/pv/mainwindow.h +++ b/pv/mainwindow.h @@ -36,10 +36,6 @@ namespace pv { class DeviceManager; -namespace device { -class DevInst; -} - namespace toolbars { class ContextBar; class SamplingBar; diff --git a/pv/popups/channels.cpp b/pv/popups/channels.cpp index 1e4bc578..5a854453 100644 --- a/pv/popups/channels.cpp +++ b/pv/popups/channels.cpp @@ -27,11 +27,12 @@ #include "channels.h" -#include #include #include #include +#include + using namespace Qt; using std::map; @@ -39,6 +40,10 @@ using std::set; using std::shared_ptr; using std::vector; +using sigrok::Channel; +using sigrok::ChannelGroup; +using sigrok::Device; + using pv::view::Signal; namespace pv { @@ -55,33 +60,25 @@ Channels::Channels(SigSession &session, QWidget *parent) : // Create the layout setLayout(&_layout); - shared_ptr dev_inst = _session.get_device(); - assert(dev_inst); - const sr_dev_inst *const sdi = dev_inst->dev_inst(); - assert(sdi); + shared_ptr device = _session.get_device(); + assert(device); // Collect a set of signals - map > signal_map; + map, shared_ptr > signal_map; const vector< shared_ptr > sigs = _session.get_signals(); for (const shared_ptr &sig : sigs) signal_map[sig->channel()] = sig; // Populate channel groups - for (const GSList *g = sdi->channel_groups; g; g = g->next) + for (auto entry : device->channel_groups()) { - const sr_channel_group *const group = - (const sr_channel_group*)g->data; - assert(group); - - // Make a set of signals and remove these signals from the + shared_ptr group = entry.second; + // Make a set of signals, and removed this signals from the // signal map. vector< shared_ptr > group_sigs; - for (const GSList *p = group->channels; p; p = p->next) + for (auto channel : group->channels()) { - const sr_channel *const channel = (const sr_channel*)p->data; - assert(channel); - const auto iter = signal_map.find(channel); if (iter == signal_map.end()) @@ -96,12 +93,9 @@ Channels::Channels(SigSession &session, QWidget *parent) : // Make a vector of the remaining channels vector< shared_ptr > global_sigs; - for (const GSList *p = sdi->channels; p; p = p->next) + for (auto channel : device->channels()) { - const sr_channel *const channel = (const sr_channel*)p->data; - assert(channel); - - const map >:: + const map, shared_ptr >:: const_iterator iter = signal_map.find(channel); if (iter != signal_map.end()) global_sigs.push_back((*iter).second); @@ -148,7 +142,7 @@ void Channels::set_all_channels(bool set) _updating_channels = false; } -void Channels::populate_group(const sr_channel_group *group, +void Channels::populate_group(shared_ptr group, const vector< shared_ptr > sigs) { using pv::prop::binding::DeviceOptions; @@ -158,14 +152,13 @@ void Channels::populate_group(const sr_channel_group *group, // popup. shared_ptr binding; if (group) - binding = shared_ptr(new DeviceOptions( - _session.get_device(), group)); + binding = shared_ptr(new DeviceOptions(group)); // Create a title if the group is going to have any content if ((!sigs.empty() || (binding && !binding->properties().empty())) && - group && group->name) + group) _layout.addRow(new QLabel( - QString("

%1

").arg(group->name))); + QString("

%1

").arg(group->name().c_str()))); // Create the channel group grid QGridLayout *const channel_grid = diff --git a/pv/popups/channels.h b/pv/popups/channels.h index 3cd9eef9..97475a57 100644 --- a/pv/popups/channels.h +++ b/pv/popups/channels.h @@ -32,11 +32,13 @@ #include -struct sr_channel_group; - class QCheckBox; class QGridLayout; +namespace sigrok { + class ChannelGroup; +} + namespace pv { class SigSession; @@ -63,7 +65,7 @@ public: private: void set_all_channels(bool set); - void populate_group(const sr_channel_group *group, + void populate_group(std::shared_ptr group, const std::vector< std::shared_ptr > sigs); QGridLayout* create_channel_group_grid( diff --git a/pv/popups/deviceoptions.cpp b/pv/popups/deviceoptions.cpp index eaa036c2..3d069f79 100644 --- a/pv/popups/deviceoptions.cpp +++ b/pv/popups/deviceoptions.cpp @@ -25,17 +25,20 @@ #include +#include + using std::shared_ptr; +using sigrok::Device; + namespace pv { namespace popups { -DeviceOptions::DeviceOptions(shared_ptr dev_inst, - QWidget *parent) : +DeviceOptions::DeviceOptions(shared_ptr device, QWidget *parent) : Popup(parent), - _dev_inst(dev_inst), + _device(device), _layout(this), - _binding(dev_inst) + _binding(device) { setLayout(&_layout); diff --git a/pv/popups/deviceoptions.h b/pv/popups/deviceoptions.h index deedf587..6d260a4d 100644 --- a/pv/popups/deviceoptions.h +++ b/pv/popups/deviceoptions.h @@ -27,6 +27,10 @@ #include #include +namespace sigrok { + class Device; +} + namespace pv { namespace popups { @@ -35,13 +39,13 @@ class DeviceOptions : public pv::widgets::Popup Q_OBJECT public: - DeviceOptions(std::shared_ptr dev_inst, + DeviceOptions(std::shared_ptr device, QWidget *parent); pv::prop::binding::DeviceOptions& binding(); private: - std::shared_ptr _dev_inst; + std::shared_ptr _device; QVBoxLayout _layout; diff --git a/pv/prop/binding/binding.cpp b/pv/prop/binding/binding.cpp index 6432d293..86318139 100644 --- a/pv/prop/binding/binding.cpp +++ b/pv/prop/binding/binding.cpp @@ -73,18 +73,18 @@ QWidget* Binding::get_property_form(QWidget *parent, return form; } -QString Binding::print_gvariant(GVariant *const gvar) +QString Binding::print_gvariant(Glib::VariantBase gvar) { QString s; - if (g_variant_is_of_type(gvar, G_VARIANT_TYPE("s"))) - s = QString::fromUtf8(g_variant_get_string(gvar, NULL)); + if (!gvar.gobj()) + s = QString::fromStdString("(null)"); + else if (gvar.is_of_type(Glib::VariantType("s"))) + s = QString::fromStdString( + Glib::VariantBase::cast_dynamic>( + gvar).get()); else - { - gchar *const text = g_variant_print(gvar, FALSE); - s = QString::fromUtf8(text); - g_free(text); - } + s = QString::fromStdString(gvar.print()); return s; } diff --git a/pv/prop/binding/binding.h b/pv/prop/binding/binding.h index cce8ebf8..9d52731d 100644 --- a/pv/prop/binding/binding.h +++ b/pv/prop/binding/binding.h @@ -21,7 +21,7 @@ #ifndef PULSEVIEW_PV_PROP_BINDING_BINDING_H #define PULSEVIEW_PV_PROP_BINDING_BINDING_H -#include +#include #include #include @@ -51,7 +51,7 @@ public: QWidget* get_property_form(QWidget *parent, bool auto_commit = false) const; - static QString print_gvariant(GVariant *const gvar); + static QString print_gvariant(Glib::VariantBase gvar); protected: std::vector< std::shared_ptr > _properties; diff --git a/pv/prop/binding/decoderoptions.cpp b/pv/prop/binding/decoderoptions.cpp index c5278c75..a01d722f 100644 --- a/pv/prop/binding/decoderoptions.cpp +++ b/pv/prop/binding/decoderoptions.cpp @@ -63,7 +63,7 @@ DecoderOptions::DecoderOptions( const Property::Getter get = [&, opt]() { return getter(opt->id); }; - const Property::Setter set = [&, opt](GVariant *value) { + const Property::Setter set = [&, opt](Glib::VariantBase value) { setter(opt->id, value); }; shared_ptr prop; @@ -90,17 +90,16 @@ shared_ptr DecoderOptions::bind_enum( const QString &name, const srd_decoder_option *option, Property::Getter getter, Property::Setter setter) { - vector< pair > values; + vector< pair > values; for (GSList *l = option->values; l; l = l->next) { - GVariant *const var = (GVariant*)l->data; - assert(var); + Glib::VariantBase var = Glib::VariantBase((GVariant*)l->data, true); values.push_back(make_pair(var, print_gvariant(var))); } return shared_ptr(new Enum(name, values, getter, setter)); } -GVariant* DecoderOptions::getter(const char *id) +Glib::VariantBase DecoderOptions::getter(const char *id) { GVariant *val = NULL; @@ -129,15 +128,15 @@ GVariant* DecoderOptions::getter(const char *id) } if (val) - g_variant_ref(val); - - return val; + return Glib::VariantBase(val, true); + else + return Glib::VariantBase(); } -void DecoderOptions::setter(const char *id, GVariant *value) +void DecoderOptions::setter(const char *id, Glib::VariantBase value) { assert(_decoder); - _decoder->set_option(id, value); + _decoder->set_option(id, value.gobj()); assert(_decoder_stack); _decoder_stack->begin_decode(); diff --git a/pv/prop/binding/decoderoptions.h b/pv/prop/binding/decoderoptions.h index a0b8dc4d..a95bc33f 100644 --- a/pv/prop/binding/decoderoptions.h +++ b/pv/prop/binding/decoderoptions.h @@ -50,9 +50,9 @@ private: const srd_decoder_option *option, Property::Getter getter, Property::Setter setter); - GVariant* getter(const char *id); + Glib::VariantBase getter(const char *id); - void setter(const char *id, GVariant *value); + void setter(const char *id, Glib::VariantBase value); private: std::shared_ptr _decoder_stack; diff --git a/pv/prop/binding/deviceoptions.cpp b/pv/prop/binding/deviceoptions.cpp index c8da5a05..0023eb2e 100644 --- a/pv/prop/binding/deviceoptions.cpp +++ b/pv/prop/binding/deviceoptions.cpp @@ -24,13 +24,12 @@ #include "deviceoptions.h" -#include #include #include #include #include -#include +#include using boost::optional; using std::function; @@ -40,44 +39,50 @@ using std::shared_ptr; using std::string; using std::vector; +using sigrok::Capability; +using sigrok::Configurable; +using sigrok::ConfigKey; +using sigrok::Error; + namespace pv { namespace prop { namespace binding { -DeviceOptions::DeviceOptions(shared_ptr dev_inst, - const sr_channel_group *group) : - _dev_inst(dev_inst), - _group(group) +DeviceOptions::DeviceOptions(shared_ptr configurable) : + _configurable(configurable) { - assert(dev_inst); - - GVariant *gvar_opts; - gsize num_opts; + assert(configurable); - if (!(gvar_opts = dev_inst->list_config(group, SR_CONF_DEVICE_OPTIONS))) - /* Driver supports no device instance options. */ - return; + for (auto entry : configurable->config_keys(ConfigKey::DEVICE_OPTIONS)) { + auto key = entry.first; + auto capabilities = entry.second; - const int *const options = (const int32_t *)g_variant_get_fixed_array( - gvar_opts, &num_opts, sizeof(int32_t)); - for (unsigned int i = 0; i < num_opts; i++) { - const struct sr_config_info *const info = - sr_config_info_get(options[i] & SR_CONF_MASK); + Glib::VariantContainerBase gvar_list; - if (!info) + if (!capabilities.count(Capability::GET) || + !capabilities.count(Capability::SET)) continue; - const int key = info->key; - GVariant *const gvar_list = dev_inst->list_config(group, key); + if (capabilities.count(Capability::LIST)) + gvar_list = configurable->config_list(key); - const QString name = QString::fromUtf8(info->name); + string name_str; + try { + name_str = key->description(); + } catch (Error e) { + name_str = key->name(); + } + + const QString name = QString::fromStdString(name_str); const Property::Getter get = [&, key]() { - return _dev_inst->get_config(_group, key); }; - const Property::Setter set = [&, key](GVariant *value) { - _dev_inst->set_config(_group, key, value); }; + return _configurable->config_get(key); }; + const Property::Setter set = [&, key](Glib::VariantBase value) { + _configurable->config_set(key, value); + config_changed(); + }; - switch(key) + switch (key->id()) { case SR_CONF_SAMPLERATE: // Sample rate values are not bound because they are shown @@ -96,7 +101,7 @@ DeviceOptions::DeviceOptions(shared_ptr dev_inst, case SR_CONF_FILTER: case SR_CONF_COUPLING: case SR_CONF_CLOCK_EDGE: - bind_enum(name, key, gvar_list, get, set); + bind_enum(name, gvar_list, get, set); break; case SR_CONF_EXTERNAL_CLOCK: @@ -105,51 +110,42 @@ DeviceOptions::DeviceOptions(shared_ptr dev_inst, break; case SR_CONF_TIMEBASE: - bind_enum(name, key, gvar_list, - get, set, print_timebase); + bind_enum(name, gvar_list, get, set, print_timebase); break; case SR_CONF_VDIV: - bind_enum(name, key, gvar_list, get, set, print_vdiv); + bind_enum(name, gvar_list, get, set, print_vdiv); break; case SR_CONF_VOLTAGE_THRESHOLD: - bind_enum(name, key, gvar_list, - get, set, print_voltage_threshold); + bind_enum(name, gvar_list, get, set, print_voltage_threshold); break; - } - if (gvar_list) - g_variant_unref(gvar_list); + default: + break; + } } - g_variant_unref(gvar_opts); } void DeviceOptions::bind_bool(const QString &name, Property::Getter getter, Property::Setter setter) { - assert(_dev_inst); + assert(_configurable); _properties.push_back(shared_ptr(new Bool( name, getter, setter))); } -void DeviceOptions::bind_enum(const QString &name, int key, - GVariant *const gvar_list, Property::Getter getter, - Property::Setter setter, function printer) +void DeviceOptions::bind_enum(const QString &name, + Glib::VariantContainerBase gvar_list, Property::Getter getter, + Property::Setter setter, function printer) { - GVariant *gvar; - GVariantIter iter; - vector< pair > values; - - assert(_dev_inst); - if (!gvar_list) { - qDebug() << "Config key " << key << " was listed, but no " - "options were given"; - return; - } + Glib::VariantBase gvar; + vector< pair > values; + + assert(_configurable); - g_variant_iter_init (&iter, gvar_list); - while ((gvar = g_variant_iter_next_value (&iter))) + Glib::VariantIter iter(gvar_list); + while ((iter.next_value(gvar))) values.push_back(make_pair(gvar, printer(gvar))); _properties.push_back(shared_ptr(new Enum(name, values, @@ -160,30 +156,30 @@ void DeviceOptions::bind_int(const QString &name, QString suffix, optional< std::pair > range, Property::Getter getter, Property::Setter setter) { - assert(_dev_inst); + assert(_configurable); _properties.push_back(shared_ptr(new Int(name, suffix, range, getter, setter))); } -QString DeviceOptions::print_timebase(GVariant *const gvar) +QString DeviceOptions::print_timebase(Glib::VariantBase gvar) { uint64_t p, q; - g_variant_get(gvar, "(tt)", &p, &q); + g_variant_get(gvar.gobj(), "(tt)", &p, &q); return QString::fromUtf8(sr_period_string(p * q)); } -QString DeviceOptions::print_vdiv(GVariant *const gvar) +QString DeviceOptions::print_vdiv(Glib::VariantBase gvar) { uint64_t p, q; - g_variant_get(gvar, "(tt)", &p, &q); + g_variant_get(gvar.gobj(), "(tt)", &p, &q); return QString::fromUtf8(sr_voltage_string(p, q)); } -QString DeviceOptions::print_voltage_threshold(GVariant *const gvar) +QString DeviceOptions::print_voltage_threshold(Glib::VariantBase gvar) { gdouble lo, hi; - g_variant_get(gvar, "(dd)", &lo, &hi); + g_variant_get(gvar.gobj(), "(dd)", &lo, &hi); return QString("L<%1V H>%2V").arg(lo, 0, 'f', 1).arg(hi, 0, 'f', 1); } diff --git a/pv/prop/binding/deviceoptions.h b/pv/prop/binding/deviceoptions.h index a1efd06a..a7fffa30 100644 --- a/pv/prop/binding/deviceoptions.h +++ b/pv/prop/binding/deviceoptions.h @@ -23,50 +23,48 @@ #include +#include #include -#include - #include "binding.h" #include -struct sr_dev_inst; -struct sr_channel_group; +namespace sigrok { + class Configurable; +} namespace pv { -namespace device { -class DevInst; -} - namespace prop { namespace binding { -class DeviceOptions : public Binding +class DeviceOptions : public QObject, public Binding { + Q_OBJECT + public: - DeviceOptions(std::shared_ptr dev_inst, - const sr_channel_group *group = NULL); + DeviceOptions(std::shared_ptr configurable); + +Q_SIGNALS: + void config_changed(); private: void bind_bool(const QString &name, Property::Getter getter, Property::Setter setter); - void bind_enum(const QString &name, int key, - GVariant *const gvar_list, + void bind_enum(const QString &name, Glib::VariantContainerBase gvar_list, Property::Getter getter, Property::Setter setter, - std::function printer = print_gvariant); + std::function printer = print_gvariant); void bind_int(const QString &name, QString suffix, boost::optional< std::pair > range, Property::Getter getter, Property::Setter setter); - static QString print_timebase(GVariant *const gvar); - static QString print_vdiv(GVariant *const gvar); - static QString print_voltage_threshold(GVariant *const gvar); + static QString print_timebase(Glib::VariantBase gvar); + static QString print_vdiv(Glib::VariantBase gvar); + static QString print_voltage_threshold(Glib::VariantBase gvar); protected: - std::shared_ptr _dev_inst; - const sr_channel_group *const _group; + std::shared_ptr _configurable; }; } // binding diff --git a/pv/prop/bool.cpp b/pv/prop/bool.cpp index e0e052fc..699656f7 100644 --- a/pv/prop/bool.cpp +++ b/pv/prop/bool.cpp @@ -42,14 +42,18 @@ QWidget* Bool::get_widget(QWidget *parent, bool auto_commit) if (_check_box) return _check_box; - GVariant *const value = _getter ? _getter() : NULL; - if (!value) + if (!_getter) return NULL; + Glib::VariantBase variant = _getter(); + if (!variant.gobj()) + return NULL; + + bool value = Glib::VariantBase::cast_dynamic>( + variant).get(); + _check_box = new QCheckBox(name(), parent); - _check_box->setCheckState(g_variant_get_boolean(value) ? - Qt::Checked : Qt::Unchecked); - g_variant_unref(value); + _check_box->setCheckState(value ? Qt::Checked : Qt::Unchecked); if (auto_commit) connect(_check_box, SIGNAL(stateChanged(int)), @@ -70,7 +74,7 @@ void Bool::commit() if (!_check_box) return; - _setter(g_variant_new_boolean( + _setter(Glib::Variant::create( _check_box->checkState() == Qt::Checked)); } diff --git a/pv/prop/double.cpp b/pv/prop/double.cpp index 93b45d32..54540bc6 100644 --- a/pv/prop/double.cpp +++ b/pv/prop/double.cpp @@ -55,10 +55,16 @@ QWidget* Double::get_widget(QWidget *parent, bool auto_commit) if (_spin_box) return _spin_box; - GVariant *const value = _getter ? _getter() : NULL; - if (!value) + if (!_getter) return NULL; + Glib::VariantBase variant = _getter(); + if (!variant.gobj()) + return NULL; + + double value = Glib::VariantBase::cast_dynamic>( + variant).get(); + _spin_box = new QDoubleSpinBox(parent); _spin_box->setDecimals(_decimals); _spin_box->setSuffix(_suffix); @@ -67,8 +73,7 @@ QWidget* Double::get_widget(QWidget *parent, bool auto_commit) if (_step) _spin_box->setSingleStep(*_step); - _spin_box->setValue(g_variant_get_double(value)); - g_variant_unref(value); + _spin_box->setValue(value); if (auto_commit) connect(_spin_box, SIGNAL(valueChanged(double)), @@ -84,7 +89,7 @@ void Double::commit() if (!_spin_box) return; - _setter(g_variant_new_double(_spin_box->value())); + _setter(Glib::Variant::create(_spin_box->value())); } void Double::on_value_changed(double) diff --git a/pv/prop/enum.cpp b/pv/prop/enum.cpp index 6439a725..03524344 100644 --- a/pv/prop/enum.cpp +++ b/pv/prop/enum.cpp @@ -31,22 +31,16 @@ namespace pv { namespace prop { Enum::Enum(QString name, - vector > values, + vector > values, Getter getter, Setter setter) : Property(name, getter, setter), _values(values), _selector(NULL) { - for (vector< pair >::const_iterator i = - _values.begin(); i != _values.end(); i++) - g_variant_ref((*i).first); } Enum::~Enum() { - for (vector< pair >::const_iterator i = - _values.begin(); i != _values.end(); i++) - g_variant_unref((*i).first); } QWidget* Enum::get_widget(QWidget *parent, bool auto_commit) @@ -54,20 +48,21 @@ QWidget* Enum::get_widget(QWidget *parent, bool auto_commit) if (_selector) return _selector; - GVariant *const value = _getter ? _getter() : NULL; - if (!value) + if (!_getter) + return NULL; + + Glib::VariantBase variant = _getter(); + if (!variant.gobj()) return NULL; _selector = new QComboBox(parent); for (unsigned int i = 0; i < _values.size(); i++) { - const pair &v = _values[i]; - _selector->addItem(v.second, qVariantFromValue((void*)v.first)); - if (value && g_variant_equal(v.first, value)) + const pair &v = _values[i]; + _selector->addItem(v.second, qVariantFromValue(v.first)); + if (v.first.equal(variant)) _selector->setCurrentIndex(i); } - g_variant_unref(value); - if (auto_commit) connect(_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(on_current_item_changed(int))); @@ -86,7 +81,7 @@ void Enum::commit() if (index < 0) return; - _setter((GVariant*)_selector->itemData(index).value()); + _setter(_selector->itemData(index).value()); } void Enum::on_current_item_changed(int) diff --git a/pv/prop/enum.h b/pv/prop/enum.h index eff6647a..6ff785a3 100644 --- a/pv/prop/enum.h +++ b/pv/prop/enum.h @@ -26,6 +26,10 @@ #include "property.h" +#include + +Q_DECLARE_METATYPE(Glib::VariantBase); + class QComboBox; namespace pv { @@ -36,7 +40,7 @@ class Enum : public Property Q_OBJECT; public: - Enum(QString name, std::vector > values, + Enum(QString name, std::vector > values, Getter getter, Setter setter); virtual ~Enum(); @@ -49,7 +53,7 @@ private Q_SLOTS: void on_current_item_changed(int); private: - const std::vector< std::pair > _values; + const std::vector< std::pair > _values; QComboBox *_selector; }; diff --git a/pv/prop/int.cpp b/pv/prop/int.cpp index 8124f9b0..45113ac7 100644 --- a/pv/prop/int.cpp +++ b/pv/prop/int.cpp @@ -41,15 +41,12 @@ Int::Int(QString name, Property(name, getter, setter), _suffix(suffix), _range(range), - _value(NULL), _spin_box(NULL) { } Int::~Int() { - if (_value) - g_variant_unref(_value); } QWidget* Int::get_widget(QWidget *parent, bool auto_commit) @@ -59,52 +56,54 @@ QWidget* Int::get_widget(QWidget *parent, bool auto_commit) if (_spin_box) return _spin_box; - if (_value) - g_variant_unref(_value); + if (!_getter) + return NULL; + + _value = _getter(); - _value = _getter ? _getter() : NULL; - if (!_value) + GVariant *value = _value.gobj(); + if (!value) return NULL; _spin_box = new QSpinBox(parent); _spin_box->setSuffix(_suffix); - const GVariantType *const type = g_variant_get_type(_value); + const GVariantType *const type = g_variant_get_type(value); assert(type); if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE)) { - int_val = g_variant_get_byte(_value); + int_val = g_variant_get_byte(value); range_min = 0, range_max = UINT8_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16)) { - int_val = g_variant_get_int16(_value); + int_val = g_variant_get_int16(value); range_min = INT16_MIN, range_max = INT16_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16)) { - int_val = g_variant_get_uint16(_value); + int_val = g_variant_get_uint16(value); range_min = 0, range_max = UINT16_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32)) { - int_val = g_variant_get_int32(_value); + int_val = g_variant_get_int32(value); range_min = INT32_MIN, range_max = INT32_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32)) { - int_val = g_variant_get_uint32(_value); + int_val = g_variant_get_uint32(value); range_min = 0, range_max = UINT32_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64)) { - int_val = g_variant_get_int64(_value); + int_val = g_variant_get_int64(value); range_min = INT64_MIN, range_max = INT64_MAX; } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64)) { - int_val = g_variant_get_uint64(_value); + int_val = g_variant_get_uint64(value); range_min = 0, range_max = UINT64_MAX; } else @@ -142,10 +141,8 @@ void Int::commit() if (!_spin_box) return; - assert(_value); - GVariant *new_value = NULL; - const GVariantType *const type = g_variant_get_type(_value); + const GVariantType *const type = g_variant_get_type(_value.gobj()); assert(type); if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE)) @@ -170,11 +167,9 @@ void Int::commit() assert(new_value); - g_variant_unref(_value); - g_variant_ref(new_value); - _value = new_value; + _value = Glib::VariantBase(new_value); - _setter(new_value); + _setter(_value); } void Int::on_value_changed(int) diff --git a/pv/prop/int.h b/pv/prop/int.h index 1a3180a1..1de99d67 100644 --- a/pv/prop/int.h +++ b/pv/prop/int.h @@ -54,7 +54,7 @@ private: const QString _suffix; const boost::optional< std::pair > _range; - GVariant *_value; + Glib::VariantBase _value; QSpinBox *_spin_box; }; diff --git a/pv/prop/property.h b/pv/prop/property.h index b3aa1a69..0d1b5316 100644 --- a/pv/prop/property.h +++ b/pv/prop/property.h @@ -21,7 +21,7 @@ #ifndef PULSEVIEW_PV_PROP_PROPERTY_H #define PULSEVIEW_PV_PROP_PROPERTY_H -#include +#include #include #include @@ -37,8 +37,8 @@ class Property : public QObject Q_OBJECT; public: - typedef std::function Getter; - typedef std::function Setter; + typedef std::function Getter; + typedef std::function Setter; protected: Property(QString name, Getter getter, Setter setter); diff --git a/pv/prop/string.cpp b/pv/prop/string.cpp index 7fcc6569..511fe6c4 100644 --- a/pv/prop/string.cpp +++ b/pv/prop/string.cpp @@ -25,6 +25,10 @@ #include "string.h" +using std::string; + +using Glib::ustring; + namespace pv { namespace prop { @@ -41,14 +45,18 @@ QWidget* String::get_widget(QWidget *parent, bool auto_commit) if (_line_edit) return _line_edit; - GVariant *const value = _getter ? _getter() : NULL; - if (!value) + if (!_getter) return NULL; + Glib::VariantBase variant = _getter(); + if (!variant.gobj()) + return NULL; + + string value = Glib::VariantBase::cast_dynamic>( + variant).get(); + _line_edit = new QLineEdit(parent); - _line_edit->setText(QString::fromUtf8( - g_variant_get_string(value, NULL))); - g_variant_unref(value); + _line_edit->setText(QString::fromStdString(value)); if (auto_commit) connect(_line_edit, SIGNAL(textEdited(const QString&)), @@ -65,7 +73,7 @@ void String::commit() return; QByteArray ba = _line_edit->text().toLocal8Bit(); - _setter(g_variant_new_string(ba.data())); + _setter(Glib::Variant::create(ba.data())); } void String::on_text_edited(const QString&) diff --git a/pv/sigsession.cpp b/pv/sigsession.cpp index 90854c7d..2e49422f 100644 --- a/pv/sigsession.cpp +++ b/pv/sigsession.cpp @@ -25,8 +25,6 @@ #include "sigsession.h" #include "devicemanager.h" -#include "device/device.h" -#include "device/file.h" #include "data/analog.h" #include "data/analogsnapshot.h" @@ -47,6 +45,8 @@ #include +#include + using std::dynamic_pointer_cast; using std::function; using std::lock_guard; @@ -58,81 +58,106 @@ using std::shared_ptr; using std::string; using std::vector; -namespace pv { +using sigrok::Analog; +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; +using sigrok::Packet; +using sigrok::PacketPayload; +using sigrok::Session; +using sigrok::SessionDevice; + +using Glib::VariantBase; +using Glib::Variant; -// TODO: This should not be necessary -SigSession* SigSession::_session = NULL; +namespace pv { // TODO: This should not be necessary -struct sr_session *SigSession::_sr_session = NULL; +shared_ptr SigSession::_sr_session = nullptr; SigSession::SigSession(DeviceManager &device_manager) : _device_manager(device_manager), _capture_state(Stopped) { // TODO: This should not be necessary - _session = this; + _sr_session = device_manager.context()->create_session(); set_default_device(); } SigSession::~SigSession() { - using pv::device::Device; - // Stop and join to the thread stop_capture(); - - if (_dev_inst) - _dev_inst->release(); - - // TODO: This should not be necessary - _session = NULL; } -shared_ptr SigSession::get_device() const +shared_ptr SigSession::get_device() const { - return _dev_inst; + return _device; } -void SigSession::set_device( - shared_ptr dev_inst) throw(QString) +void SigSession::set_device(shared_ptr device) { - using pv::device::Device; - - if (!dev_inst) - return; - // Ensure we are not capturing before setting the device stop_capture(); - if (_dev_inst) { - sr_session_datafeed_callback_remove_all(_sr_session); - _dev_inst->release(); + // Are we setting a session device? + auto session_device = dynamic_pointer_cast(device); + // Did we have a session device selected previously? + auto prev_session_device = dynamic_pointer_cast(_device); + + if (_device) { + _sr_session->remove_datafeed_callbacks(); + if (!prev_session_device) { + _device->close(); + _sr_session->remove_devices(); + } } - _dev_inst = dev_inst; + if (session_device) + _sr_session = session_device->parent(); + + _device = device; _decode_traces.clear(); - if (dev_inst) { - dev_inst->use(this); - sr_session_datafeed_callback_add(_sr_session, data_feed_in_proc, NULL); - update_signals(dev_inst); + if (device) { + if (!session_device) + { + _sr_session = _device_manager.context()->create_session(); + device->open(); + _sr_session->add_device(device); + } + _sr_session->add_datafeed_callback([=] + (shared_ptr device, shared_ptr packet) { + data_feed_in(device, packet); + }); + update_signals(device); } } -void SigSession::set_file(const string &name) throw(QString) +void SigSession::set_file(const string &name) { - // Deselect the old device, because file type detection in File::create - // destroys the old session inside libsigrok. - set_device(shared_ptr()); - set_device(shared_ptr(device::File::create(name))); + _sr_session = _device_manager.context()->load_session(name); + _device = _sr_session->devices()[0]; + _decode_traces.clear(); + _sr_session->add_datafeed_callback([=] + (shared_ptr device, shared_ptr packet) { + data_feed_in(device, packet); + }); + update_signals(_device); } void SigSession::set_default_device() { - shared_ptr default_device; - const list< shared_ptr > &devices = + shared_ptr default_device; + const list< shared_ptr > &devices = _device_manager.devices(); if (!devices.empty()) { @@ -140,24 +165,14 @@ void SigSession::set_default_device() default_device = devices.front(); // Try and find the demo device and select that by default - for (shared_ptr dev : devices) - if (strcmp(dev->dev_inst()->driver->name, - "demo") == 0) { + for (shared_ptr dev : devices) + if (dev->driver()->name().compare("demo") == 0) { default_device = dev; break; } - } - - set_device(default_device); -} - -void SigSession::release_device(device::DevInst *dev_inst) -{ - (void)dev_inst; - assert(_dev_inst.get() == dev_inst); - assert(_capture_state == Stopped); - _dev_inst = shared_ptr(); + set_device(default_device); + } } SigSession::capture_state SigSession::get_capture_state() const @@ -171,37 +186,31 @@ void SigSession::start_capture(function error_handler) stop_capture(); // Check that a device instance has been selected. - if (!_dev_inst) { + if (!_device) { qDebug() << "No device selected"; return; } - assert(_dev_inst->dev_inst()); - // Check that at least one channel is enabled - const GSList *l; - for (l = _dev_inst->dev_inst()->channels; l; l = l->next) { - sr_channel *const channel = (sr_channel*)l->data; - assert(channel); - if (channel->enabled) - break; - } + auto channels = _device->channels(); + bool enabled = std::any_of(channels.begin(), channels.end(), + [](shared_ptr channel) { return channel->enabled(); }); - if (!l) { + if (!enabled) { error_handler(tr("No channels enabled.")); return; } // Begin the session _sampling_thread = std::thread( - &SigSession::sample_thread_proc, this, _dev_inst, + &SigSession::sample_thread_proc, this, _device, error_handler); } void SigSession::stop_capture() { if (get_capture_state() != Stopped) - sr_session_stop(_sr_session); + _sr_session->stop(); // Check that sampling stopped if (_sampling_thread.joinable()) @@ -310,32 +319,20 @@ void SigSession::set_capture_state(capture_state state) capture_state_changed(state); } -void SigSession::update_signals(shared_ptr dev_inst) +void SigSession::update_signals(shared_ptr device) { - assert(dev_inst); + assert(device); assert(_capture_state == Stopped); - unsigned int logic_channel_count = 0; - // Clear the decode traces _decode_traces.clear(); // Detect what data types we will receive - if(dev_inst) { - assert(dev_inst->dev_inst()); - for (const GSList *l = dev_inst->dev_inst()->channels; - l; l = l->next) { - const sr_channel *const channel = (const sr_channel *)l->data; - if (!channel->enabled) - continue; - - switch(channel->type) { - case SR_CHANNEL_LOGIC: - logic_channel_count++; - break; - } - } - } + auto channels = device->channels(); + unsigned int logic_channel_count = std::count_if( + channels.begin(), channels.end(), + [] (shared_ptr channel) { + return channel->type() == ChannelType::LOGIC; }); // Create data containers for the logic data snapshots { @@ -355,21 +352,13 @@ void SigSession::update_signals(shared_ptr dev_inst) _signals.clear(); - if(!dev_inst) - break; - - assert(dev_inst->dev_inst()); - for (const GSList *l = dev_inst->dev_inst()->channels; - l; l = l->next) { + for (auto channel : device->channels()) { shared_ptr signal; - sr_channel *const channel = (sr_channel *)l->data; - assert(channel); - switch(channel->type) { + switch(channel->type()->id()) { case SR_CHANNEL_LOGIC: signal = shared_ptr( - new view::LogicSignal(dev_inst, - channel, _logic_data)); + new view::LogicSignal(device, channel, _logic_data)); break; case SR_CHANNEL_ANALOG: @@ -377,8 +366,7 @@ void SigSession::update_signals(shared_ptr dev_inst) shared_ptr data( new data::Analog()); signal = shared_ptr( - new view::AnalogSignal(dev_inst, - channel, data)); + new view::AnalogSignal(channel, data)); break; } @@ -397,7 +385,7 @@ void SigSession::update_signals(shared_ptr dev_inst) } shared_ptr SigSession::signal_from_channel( - const sr_channel *channel) const + shared_ptr channel) const { lock_guard lock(_signals_mutex); for (shared_ptr sig : _signals) { @@ -408,24 +396,10 @@ shared_ptr SigSession::signal_from_channel( return shared_ptr(); } -void SigSession::read_sample_rate(const sr_dev_inst *const sdi) +void SigSession::read_sample_rate(shared_ptr device) { - GVariant *gvar; - uint64_t sample_rate = 0; - - // Read out the sample rate - if(sdi->driver) - { - const int ret = sr_config_get(sdi->driver, sdi, NULL, - SR_CONF_SAMPLERATE, &gvar); - if (ret != SR_OK) { - qDebug("Failed to get samplerate\n"); - return; - } - - sample_rate = g_variant_get_uint64(gvar); - g_variant_unref(gvar); - } + uint64_t sample_rate = VariantBase::cast_dynamic>( + device->config_get(ConfigKey::SAMPLERATE)).get(); // Set the sample rate of all data const set< shared_ptr > data_set = get_data(); @@ -435,26 +409,25 @@ void SigSession::read_sample_rate(const sr_dev_inst *const sdi) } } -void SigSession::sample_thread_proc(shared_ptr dev_inst, +void SigSession::sample_thread_proc(shared_ptr device, function error_handler) { - assert(dev_inst); - assert(dev_inst->dev_inst()); + assert(device); assert(error_handler); - read_sample_rate(dev_inst->dev_inst()); + read_sample_rate(device); try { - dev_inst->start(); - } catch(const QString e) { - error_handler(e); + _sr_session->start(); + } catch(Error e) { + error_handler(e.what()); return; } - set_capture_state(sr_session_trigger_get(_sr_session) ? + set_capture_state(_sr_session->trigger() ? AwaitingTrigger : Running); - dev_inst->run(); + _sr_session->run(); set_capture_state(Stopped); // Confirm that SR_DF_END was received @@ -465,22 +438,20 @@ void SigSession::sample_thread_proc(shared_ptr dev_inst, } } -void SigSession::feed_in_header(const sr_dev_inst *sdi) +void SigSession::feed_in_header(shared_ptr device) { - read_sample_rate(sdi); + read_sample_rate(device); } -void SigSession::feed_in_meta(const sr_dev_inst *sdi, - const sr_datafeed_meta &meta) +void SigSession::feed_in_meta(shared_ptr device, + shared_ptr meta) { - (void)sdi; + (void)device; - for (const GSList *l = meta.config; l; l = l->next) { - const sr_config *const src = (const sr_config*)l->data; - switch (src->key) { + for (auto entry : meta->config()) { + switch (entry.first->id()) { case SR_CONF_SAMPLERATE: /// @todo handle samplerate changes - /// samplerate = (uint64_t *)src->value; break; default: // Unknown metadata is not an error. @@ -497,7 +468,7 @@ void SigSession::feed_in_frame_begin() frame_began(); } -void SigSession::feed_in_logic(const sr_datafeed_logic &logic) +void SigSession::feed_in_logic(shared_ptr logic) { lock_guard lock(_data_mutex); @@ -512,9 +483,18 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) // This could be the first packet after a trigger set_capture_state(Running); + // Get sample limit. + uint64_t sample_limit; + try { + sample_limit = VariantBase::cast_dynamic>( + _device->config_get(ConfigKey::LIMIT_SAMPLES)).get(); + } catch (Error) { + sample_limit = 0; + } + // Create a new data snapshot _cur_logic_snapshot = shared_ptr( - new data::LogicSnapshot(logic, _dev_inst->get_sample_limit())); + new data::LogicSnapshot(logic, sample_limit)); _logic_data->push_snapshot(_cur_logic_snapshot); // @todo Putting this here means that only listeners querying @@ -532,24 +512,22 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) data_received(); } -void SigSession::feed_in_analog(const sr_datafeed_analog &analog) +void SigSession::feed_in_analog(shared_ptr analog) { lock_guard lock(_data_mutex); - const unsigned int channel_count = g_slist_length(analog.channels); - const size_t sample_count = analog.num_samples / channel_count; - const float *data = analog.data; + const vector> channels = analog->channels(); + const unsigned int channel_count = channels.size(); + const size_t sample_count = analog->num_samples() / channel_count; + const float *data = analog->data_pointer(); bool sweep_beginning = false; - for (GSList *p = analog.channels; p; p = p->next) + for (auto channel : channels) { shared_ptr snapshot; - sr_channel *const channel = (sr_channel*)p->data; - assert(channel); - // Try to get the snapshot of the channel - const map< const sr_channel*, shared_ptr >:: + const map< shared_ptr, shared_ptr >:: iterator iter = _cur_analog_snapshots.find(channel); if (iter != _cur_analog_snapshots.end()) snapshot = (*iter).second; @@ -560,9 +538,18 @@ void SigSession::feed_in_analog(const sr_datafeed_analog &analog) // in the sweep containing this snapshot. sweep_beginning = true; + // Get sample limit. + uint64_t sample_limit; + try { + sample_limit = VariantBase::cast_dynamic>( + _device->config_get(ConfigKey::LIMIT_SAMPLES)).get(); + } catch (Error) { + sample_limit = 0; + } + // Create a snapshot, keep it in the maps of channels snapshot = shared_ptr( - new data::AnalogSnapshot(_dev_inst->get_sample_limit())); + new data::AnalogSnapshot(sample_limit)); _cur_analog_snapshots[channel] = snapshot; // Find the annalog data associated with the channel @@ -593,21 +580,18 @@ void SigSession::feed_in_analog(const sr_datafeed_analog &analog) data_received(); } -void SigSession::data_feed_in(const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet) +void SigSession::data_feed_in(shared_ptr device, shared_ptr packet) { - assert(sdi); + assert(device); assert(packet); - switch (packet->type) { + switch (packet->type()->id()) { case SR_DF_HEADER: - feed_in_header(sdi); + feed_in_header(device); break; case SR_DF_META: - assert(packet->payload); - feed_in_meta(sdi, - *(const sr_datafeed_meta*)packet->payload); + feed_in_meta(device, dynamic_pointer_cast(packet->payload())); break; case SR_DF_FRAME_BEGIN: @@ -615,13 +599,11 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi, break; case SR_DF_LOGIC: - assert(packet->payload); - feed_in_logic(*(const sr_datafeed_logic*)packet->payload); + feed_in_logic(dynamic_pointer_cast(packet->payload())); break; case SR_DF_ANALOG: - assert(packet->payload); - feed_in_analog(*(const sr_datafeed_analog*)packet->payload); + feed_in_analog(dynamic_pointer_cast(packet->payload())); break; case SR_DF_END: @@ -639,12 +621,4 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi, } } -void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, void *cb_data) -{ - (void) cb_data; - assert(_session); - _session->data_feed_in(sdi, packet); -} - } // namespace pv diff --git a/pv/sigsession.h b/pv/sigsession.h index 9359176c..a624d1d2 100644 --- a/pv/sigsession.h +++ b/pv/sigsession.h @@ -32,11 +32,19 @@ #include #include -#include - struct srd_decoder; struct srd_channel; +namespace sigrok { + class Analog; + class Channel; + class Device; + class Logic; + class Meta; + class Packet; + class Session; +} + namespace pv { class DeviceManager; @@ -49,10 +57,6 @@ class LogicSnapshot; class SignalData; } -namespace device { -class DevInst; -} - namespace view { class DecodeTrace; class LogicSignal; @@ -75,21 +79,17 @@ public: ~SigSession(); - std::shared_ptr get_device() const; + std::shared_ptr get_device() const; /** * Sets device instance that will be used in the next capture session. */ - void set_device(std::shared_ptr dev_inst) - throw(QString); + void set_device(std::shared_ptr device); - void set_file(const std::string &name) - throw(QString); + void set_file(const std::string &name); void set_default_device(); - void release_device(device::DevInst *dev_inst); - capture_state get_capture_state() const; void start_capture(std::function error_handler); @@ -113,33 +113,30 @@ public: private: void set_capture_state(capture_state state); - void update_signals(std::shared_ptr dev_inst); + void update_signals(std::shared_ptr device); std::shared_ptr signal_from_channel( - const sr_channel *channel) const; + std::shared_ptr channel) const; - void read_sample_rate(const sr_dev_inst *const sdi); + void read_sample_rate(std::shared_ptr); private: - void sample_thread_proc(std::shared_ptr dev_inst, + void sample_thread_proc(std::shared_ptr device, std::function error_handler); - void feed_in_header(const sr_dev_inst *sdi); + void feed_in_header(std::shared_ptr device); - void feed_in_meta(const sr_dev_inst *sdi, - const sr_datafeed_meta &meta); + void feed_in_meta(std::shared_ptr device, + std::shared_ptr meta); void feed_in_frame_begin(); - void feed_in_logic(const sr_datafeed_logic &logic); - - void feed_in_analog(const sr_datafeed_analog &analog); + void feed_in_logic(std::shared_ptr logic); - void data_feed_in(const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet); + void feed_in_analog(std::shared_ptr analog); - static void data_feed_in_proc(const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, void *cb_data); + void data_feed_in(std::shared_ptr device, + std::shared_ptr packet); private: DeviceManager &_device_manager; @@ -147,7 +144,7 @@ private: /** * The device instance that will be used in the next capture session. */ - std::shared_ptr _dev_inst; + std::shared_ptr _device; std::vector< std::shared_ptr > _decode_traces; @@ -160,7 +157,7 @@ private: mutable std::mutex _data_mutex; std::shared_ptr _logic_data; std::shared_ptr _cur_logic_snapshot; - std::map< const sr_channel*, std::shared_ptr > + std::map< std::shared_ptr, std::shared_ptr > _cur_analog_snapshots; std::thread _sampling_thread; @@ -176,21 +173,13 @@ Q_SIGNALS: void frame_ended(); -private: - // TODO: This should not be necessary. Multiple concurrent - // sessions should should be supported and it should be - // possible to associate a pointer with a sr_session. - static SigSession *_session; - public: - // TODO: Even more of a hack. The libsigrok API now allows for - // multiple sessions. However sr_session_* calls are scattered - // around the PV architecture and a single SigSession object is - // being used across multiple sequential sessions, which are - // created and destroyed in other classes in pv::device. This - // is a mess. For now just keep a single sr_session pointer here - // which we can use for all those scattered calls. - static struct sr_session *_sr_session; + // Hack. The libsigrok API now allows for multiple sessions. However, + // sigrok::Session calls are scattered around the PV architecture and a + // single SigSession object is being used across multiple sequential + // sessions. This is a mess. For now just keep a single sigrok::Session + // pointer here which we can use for all those scattered calls. + static std::shared_ptr _sr_session; }; } // namespace pv diff --git a/pv/storesession.cpp b/pv/storesession.cpp index 9ad494e2..d5355cba 100644 --- a/pv/storesession.cpp +++ b/pv/storesession.cpp @@ -27,6 +27,8 @@ #include #include +#include + using std::deque; using std::dynamic_pointer_cast; using std::lock_guard; @@ -40,6 +42,8 @@ using std::string; using std::thread; using std::vector; +using sigrok::Error; + namespace pv { const size_t StoreSession::BlockSize = 1024 * 1024; @@ -120,8 +124,9 @@ bool StoreSession::start() channels[sigs.size()] = NULL; // Begin storing - if (sr_session_save_init(SigSession::_sr_session, _file_name.c_str(), - data->samplerate(), channels) != SR_OK) { + try { + SigSession::_sr_session->begin_save(_file_name); + } catch (Error error) { _error = tr("Error while saving."); return false; } @@ -179,9 +184,11 @@ void StoreSession::store_proc(shared_ptr snapshot) start_sample + samples_per_block, sample_count); snapshot->get_samples(data, start_sample, end_sample); - if(sr_session_append(SigSession::_sr_session, _file_name.c_str(), data, - unit_size, end_sample - start_sample) != SR_OK) - { + size_t length = end_sample - start_sample; + + try { + SigSession::_sr_session->append(data, length, unit_size); + } catch (Error error) { _error = tr("Error while saving."); break; } diff --git a/pv/toolbars/samplingbar.cpp b/pv/toolbars/samplingbar.cpp index c3437377..2350a45f 100644 --- a/pv/toolbars/samplingbar.cpp +++ b/pv/toolbars/samplingbar.cpp @@ -30,17 +30,24 @@ #include "samplingbar.h" #include -#include #include #include #include +#include + using std::map; +using std::vector; using std::max; using std::min; using std::shared_ptr; using std::string; +using sigrok::Capability; +using sigrok::ConfigKey; +using sigrok::Device; +using sigrok::Error; + namespace pv { namespace toolbars { @@ -102,8 +109,8 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) : } void SamplingBar::set_device_list( - const std::list< shared_ptr > &devices, - shared_ptr selected) + const std::map< shared_ptr, string > &device_names, + shared_ptr selected) { int selected_index = -1; @@ -112,20 +119,18 @@ void SamplingBar::set_device_list( _updating_device_selector = true; _device_selector.clear(); - _device_selector_map.clear(); - for (shared_ptr dev_inst : devices) { - assert(dev_inst); - const string title = dev_inst->format_device_title(); - const sr_dev_inst *sdi = dev_inst->dev_inst(); - assert(sdi); + for (auto entry : device_names) { + auto device = entry.first; + auto description = entry.second; - if (selected == dev_inst) + assert(device); + + if (selected == device) selected_index = _device_selector.count(); - _device_selector_map[sdi] = dev_inst; - _device_selector.addItem(title.c_str(), - qVariantFromValue((void*)sdi)); + _device_selector.addItem(description.c_str(), + qVariantFromValue(device)); } // The selected device should have been in the list @@ -137,22 +142,13 @@ void SamplingBar::set_device_list( _updating_device_selector = false; } -shared_ptr SamplingBar::get_selected_device() const +shared_ptr SamplingBar::get_selected_device() const { const int index = _device_selector.currentIndex(); if (index < 0) - return shared_ptr(); - - const sr_dev_inst *const sdi = - (const sr_dev_inst*)_device_selector.itemData( - index).value(); - assert(sdi); + return shared_ptr(); - const auto iter = _device_selector_map.find(sdi); - if (iter == _device_selector_map.end()) - return shared_ptr(); - - return shared_ptr((*iter).second); + return _device_selector.itemData(index).value>(); } void SamplingBar::set_capture_state(pv::SigSession::capture_state state) @@ -165,28 +161,30 @@ void SamplingBar::set_capture_state(pv::SigSession::capture_state state) void SamplingBar::update_sample_rate_selector() { - GVariant *gvar_dict, *gvar_list; + Glib::VariantContainerBase gvar_dict; + GVariant *gvar_list; const uint64_t *elements = NULL; gsize num_elements; if (_updating_sample_rate) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; assert(!_updating_sample_rate); _updating_sample_rate = true; - if (!(gvar_dict = dev_inst->list_config(NULL, SR_CONF_SAMPLERATE))) - { + try { + gvar_dict = device->config_list(ConfigKey::SAMPLERATE); + } catch (Error error) { _sample_rate.show_none(); _updating_sample_rate = false; return; } - if ((gvar_list = g_variant_lookup_value(gvar_dict, + if ((gvar_list = g_variant_lookup_value(gvar_dict.gobj(), "samplerate-steps", G_VARIANT_TYPE("at")))) { elements = (const uint64_t *)g_variant_get_fixed_array( @@ -214,7 +212,7 @@ void SamplingBar::update_sample_rate_selector() _sample_rate.show_min_max_step(min, max, step); } } - else if ((gvar_list = g_variant_lookup_value(gvar_dict, + else if ((gvar_list = g_variant_lookup_value(gvar_dict.gobj(), "samplerates", G_VARIANT_TYPE("at")))) { elements = (const uint64_t *)g_variant_get_fixed_array( @@ -224,44 +222,39 @@ void SamplingBar::update_sample_rate_selector() } _updating_sample_rate = false; - g_variant_unref(gvar_dict); update_sample_rate_selector_value(); } void SamplingBar::update_sample_rate_selector_value() { - GVariant *gvar; - uint64_t samplerate; - if (_updating_sample_rate) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; - if (!(gvar = dev_inst->get_config(NULL, SR_CONF_SAMPLERATE))) { + try { + auto gvar = device->config_get(ConfigKey::SAMPLERATE); + uint64_t samplerate = + Glib::VariantBase::cast_dynamic>(gvar).get(); + assert(!_updating_sample_rate); + _updating_sample_rate = true; + _sample_rate.set_value(samplerate); + _updating_sample_rate = false; + } catch (Error error) { qDebug() << "WARNING: Failed to get value of sample rate"; return; } - samplerate = g_variant_get_uint64(gvar); - g_variant_unref(gvar); - - assert(!_updating_sample_rate); - _updating_sample_rate = true; - _sample_rate.set_value(samplerate); - _updating_sample_rate = false; } void SamplingBar::update_sample_count_selector() { - GVariant *gvar; - if (_updating_sample_count) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; assert(!_updating_sample_count); @@ -276,12 +269,11 @@ void SamplingBar::update_sample_count_selector() if (sample_count == 0) sample_count = DefaultSampleCount; - if ((gvar = dev_inst->list_config(NULL, SR_CONF_LIMIT_SAMPLES))) - { - g_variant_get(gvar, "(tt)", + try { + auto gvar = device->config_list(ConfigKey::LIMIT_SAMPLES); + g_variant_get(gvar.gobj(), "(tt)", &min_sample_count, &max_sample_count); - g_variant_unref(gvar); - } + } catch (Error error) {} min_sample_count = min(max(min_sample_count, MinSampleCount), max_sample_count); @@ -289,16 +281,14 @@ void SamplingBar::update_sample_count_selector() _sample_count.show_125_list( min_sample_count, max_sample_count); - if ((gvar = dev_inst->get_config(NULL, SR_CONF_LIMIT_SAMPLES))) - { - sample_count = g_variant_get_uint64(gvar); + try { + auto gvar = device->config_get(ConfigKey::LIMIT_SAMPLES); + sample_count = g_variant_get_uint64(gvar.gobj()); if (sample_count == 0) sample_count = DefaultSampleCount; sample_count = min(max(sample_count, MinSampleCount), max_sample_count); - - g_variant_unref(gvar); - } + } catch (Error error) {} _sample_count.set_value(sample_count); } @@ -310,16 +300,14 @@ void SamplingBar::update_sample_count_selector() void SamplingBar::update_device_config_widgets() { - GVariant *gvar; - using namespace pv::popups; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; // Update the configure popup - DeviceOptions *const opts = new DeviceOptions(dev_inst, this); + DeviceOptions *const opts = new DeviceOptions(device, this); _configure_button_action->setVisible( !opts->binding().properties().empty()); _configure_button.set_popup(opts); @@ -331,31 +319,33 @@ void SamplingBar::update_device_config_widgets() // Update supported options. _sample_count_supported = false; - if ((gvar = dev_inst->list_config(NULL, SR_CONF_DEVICE_OPTIONS))) - { - gsize num_opts; - const int *const options = - (const int32_t *)g_variant_get_fixed_array( - gvar, &num_opts, sizeof(int32_t)); - for (unsigned int i = 0; i < num_opts; i++) + try { + for (auto entry : device->config_keys(ConfigKey::DEVICE_OPTIONS)) { - switch (options[i] & SR_CONF_MASK) { + auto key = entry.first; + auto capabilities = entry.second; + switch (key->id()) { case SR_CONF_LIMIT_SAMPLES: - if (options[i] & SR_CONF_SET) + if (capabilities.count(Capability::SET)) _sample_count_supported = true; break; case SR_CONF_LIMIT_FRAMES: - if (options[i] & SR_CONF_SET) - dev_inst->set_config(NULL, SR_CONF_LIMIT_FRAMES, - g_variant_new_uint64(1)); + if (capabilities.count(Capability::SET)) + { + device->config_set(ConfigKey::LIMIT_FRAMES, + Glib::Variant::create(1)); + on_config_changed(); + } + break; + default: break; } } - } + } catch (Error error) {} // Add notification of reconfigure events disconnect(this, SLOT(on_config_changed())); - connect(dev_inst.get(), SIGNAL(config_changed()), + connect(&opts->binding(), SIGNAL(config_changed()), this, SLOT(on_config_changed())); // Update sweep timing widgets. @@ -370,8 +360,8 @@ void SamplingBar::commit_sample_count() if (_updating_sample_count) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; sample_count = _sample_count.value(); @@ -379,11 +369,16 @@ void SamplingBar::commit_sample_count() // Set the sample count assert(!_updating_sample_count); _updating_sample_count = true; - if (_sample_count_supported && - !dev_inst->set_config(NULL, SR_CONF_LIMIT_SAMPLES, - g_variant_new_uint64(sample_count))) { - qDebug() << "Failed to configure sample count."; - return; + if (_sample_count_supported) + { + try { + device->config_set(ConfigKey::LIMIT_SAMPLES, + Glib::Variant::create(sample_count)); + on_config_changed(); + } catch (Error error) { + qDebug() << "Failed to configure sample count."; + return; + } } _updating_sample_count = false; } @@ -395,8 +390,8 @@ void SamplingBar::commit_sample_rate() if (_updating_sample_rate) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + const shared_ptr device = get_selected_device(); + if (!device) return; sample_rate = _sample_rate.value(); @@ -406,8 +401,11 @@ void SamplingBar::commit_sample_rate() // Set the samplerate assert(!_updating_sample_rate); _updating_sample_rate = true; - if (!dev_inst->set_config(NULL, SR_CONF_SAMPLERATE, - g_variant_new_uint64(sample_rate))) { + try { + device->config_set(ConfigKey::SAMPLERATE, + Glib::Variant::create(sample_rate)); + on_config_changed(); + } catch (Error error) { qDebug() << "Failed to configure samplerate."; return; } @@ -419,11 +417,11 @@ void SamplingBar::on_device_selected() if (_updating_device_selector) return; - const shared_ptr dev_inst = get_selected_device(); - if (!dev_inst) + shared_ptr device = get_selected_device(); + if (!device) return; - _session.set_device(dev_inst); + _session.set_device(device); update_device_config_widgets(); } diff --git a/pv/toolbars/samplingbar.h b/pv/toolbars/samplingbar.h index b2e7def2..7c0ec9af 100644 --- a/pv/toolbars/samplingbar.h +++ b/pv/toolbars/samplingbar.h @@ -23,7 +23,6 @@ #include -#include #include #include @@ -36,16 +35,18 @@ #include #include +namespace sigrok { + class Device; +} + +Q_DECLARE_METATYPE(std::shared_ptr) + class QAction; namespace pv { class SigSession; -namespace device { -class DevInst; -} - namespace toolbars { class SamplingBar : public QToolBar @@ -61,11 +62,11 @@ public: SamplingBar(SigSession &session, QWidget *parent); void set_device_list( - const std::list< std::shared_ptr > - &devices, - std::shared_ptr selected); + const std::map< std::shared_ptr, std::string > + &device_names, + std::shared_ptr selected); - std::shared_ptr get_selected_device() const; + std::shared_ptr get_selected_device() const; void set_capture_state(pv::SigSession::capture_state state); @@ -95,8 +96,6 @@ private: SigSession &_session; QComboBox _device_selector; - std::map > - _device_selector_map; bool _updating_device_selector; pv::widgets::PopupToolButton _configure_button; diff --git a/pv/view/analogsignal.cpp b/pv/view/analogsignal.cpp index e3f51aab..7b49bbd2 100644 --- a/pv/view/analogsignal.cpp +++ b/pv/view/analogsignal.cpp @@ -28,11 +28,15 @@ #include "pv/data/analogsnapshot.h" #include "pv/view/view.h" +#include + using std::max; using std::min; using std::shared_ptr; using std::deque; +using sigrok::Channel; + namespace pv { namespace view { @@ -45,13 +49,13 @@ const QColor AnalogSignal::SignalColours[4] = { const float AnalogSignal::EnvelopeThreshold = 256.0f; -AnalogSignal::AnalogSignal(shared_ptr dev_inst, - const sr_channel *const channel, shared_ptr data) : - Signal(dev_inst, channel), +AnalogSignal::AnalogSignal(shared_ptr channel, + shared_ptr data) : + Signal(channel), _data(data), _scale(1.0f) { - _colour = SignalColours[channel->index % countof(SignalColours)]; + _colour = SignalColours[_channel->index() % countof(SignalColours)]; } AnalogSignal::~AnalogSignal() @@ -75,7 +79,7 @@ void AnalogSignal::set_scale(float scale) void AnalogSignal::paint_back(QPainter &p, int left, int right) { - if (_channel->enabled) + if (_channel->enabled()) paint_axis(p, get_y(), left, right); } @@ -92,7 +96,7 @@ void AnalogSignal::paint_mid(QPainter &p, int left, int right) const double offset = _view->offset(); - if (!_channel->enabled) + if (!_channel->enabled()) return; const deque< shared_ptr > &snapshots = diff --git a/pv/view/analogsignal.h b/pv/view/analogsignal.h index 93420336..4070a8aa 100644 --- a/pv/view/analogsignal.h +++ b/pv/view/analogsignal.h @@ -42,8 +42,7 @@ private: static const float EnvelopeThreshold; public: - AnalogSignal(std::shared_ptr dev_inst, - const sr_channel *const channel, + AnalogSignal(std::shared_ptr channel, std::shared_ptr data); virtual ~AnalogSignal(); diff --git a/pv/view/logicsignal.cpp b/pv/view/logicsignal.cpp index 27635f90..54d25781 100644 --- a/pv/view/logicsignal.cpp +++ b/pv/view/logicsignal.cpp @@ -30,11 +30,12 @@ #include "view.h" #include -#include #include #include #include +#include + using std::deque; using std::max; using std::min; @@ -42,6 +43,13 @@ using std::pair; using std::shared_ptr; using std::vector; +using sigrok::Channel; +using sigrok::ConfigKey; +using sigrok::Device; +using sigrok::Error; +using sigrok::Trigger; +using sigrok::TriggerMatchType; + namespace pv { namespace view { @@ -64,9 +72,11 @@ const QColor LogicSignal::SignalColours[10] = { QColor(0xEE, 0xEE, 0xEC), // White }; -LogicSignal::LogicSignal(shared_ptr dev_inst, - const sr_channel *const channel, shared_ptr data) : - Signal(dev_inst, channel), +LogicSignal::LogicSignal(shared_ptr device, + shared_ptr channel, + shared_ptr data) : + Signal(channel), + _device(device), _data(data), _trigger_none(NULL), _trigger_rising(NULL), @@ -75,26 +85,18 @@ LogicSignal::LogicSignal(shared_ptr dev_inst, _trigger_low(NULL), _trigger_change(NULL) { - struct sr_trigger *trigger; - struct sr_trigger_stage *stage; - struct sr_trigger_match *match; - const GSList *l, *m; + shared_ptr trigger; - _colour = SignalColours[channel->index % countof(SignalColours)]; + _colour = SignalColours[channel->index() % countof(SignalColours)]; /* Populate this channel's trigger setting with whatever we * find in the current session trigger, if anything. */ - _trigger_match = 0; - if ((trigger = sr_session_trigger_get(SigSession::_sr_session))) { - for (l = trigger->stages; l && !_trigger_match; l = l->next) { - stage = (struct sr_trigger_stage *)l->data; - for (m = stage->matches; m && !_trigger_match; m = m->next) { - match = (struct sr_trigger_match *)m->data; - if (match->channel == _channel) - _trigger_match = match->match; - } - } - } + _trigger_match = nullptr; + if ((trigger = SigSession::_sr_session->trigger())) + for (auto stage : trigger->stages()) + for (auto match : stage->matches()) + if (match->channel() == _channel) + _trigger_match = match->type(); } LogicSignal::~LogicSignal() @@ -113,7 +115,7 @@ shared_ptr LogicSignal::logic_data() const void LogicSignal::paint_back(QPainter &p, int left, int right) { - if (_channel->enabled) + if (_channel->enabled()) paint_axis(p, get_y(), left, right); } @@ -137,7 +139,7 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right) const double offset = _view->offset(); - if (!_channel->enabled) + if (!_channel->enabled()) return; const float high_offset = y - View::SignalHeight + 0.5f; @@ -167,7 +169,7 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right) snapshot->get_subsampled_edges(edges, min(max((int64_t)floor(start), (int64_t)0), last_sample), min(max((int64_t)ceil(end), (int64_t)0), last_sample), - samples_per_pixel / Oversampling, _channel->index); + samples_per_pixel / Oversampling, _channel->index()); assert(edges.size() >= 2); // Paint the edges @@ -251,12 +253,12 @@ void LogicSignal::init_trigger_actions(QWidget *parent) connect(_trigger_change, SIGNAL(triggered()), this, SLOT(on_trigger())); } -QAction* LogicSignal::match_action(int match) +QAction* LogicSignal::match_action(const TriggerMatchType *type) { QAction *action; action = _trigger_none; - switch (match) { + switch (type->id()) { case SR_TRIGGER_ZERO: action = _trigger_low; break; @@ -272,56 +274,56 @@ QAction* LogicSignal::match_action(int match) case SR_TRIGGER_EDGE: action = _trigger_change; break; + default: + assert(0); } return action; } -int LogicSignal::action_match(QAction *action) +const TriggerMatchType *LogicSignal::action_match(QAction *action) { - int match; - if (action == _trigger_low) - match = SR_TRIGGER_ZERO; + return TriggerMatchType::ZERO; else if (action == _trigger_high) - match = SR_TRIGGER_ONE; + return TriggerMatchType::ONE; else if (action == _trigger_rising) - match = SR_TRIGGER_RISING; + return TriggerMatchType::RISING; else if (action == _trigger_falling) - match = SR_TRIGGER_FALLING; + return TriggerMatchType::FALLING; else if (action == _trigger_change) - match = SR_TRIGGER_EDGE; + return TriggerMatchType::EDGE; else - match = 0; - - return match; + return nullptr; } void LogicSignal::populate_popup_form(QWidget *parent, QFormLayout *form) { - GVariant *gvar; - gsize num_opts; - const int32_t *trig_matches; - unsigned int i; + Glib::VariantContainerBase gvar; + vector trig_types; bool is_checked; Signal::populate_popup_form(parent, form); - if (!(gvar = _dev_inst->list_config(NULL, SR_CONF_TRIGGER_MATCH))) + try { + gvar = _device->config_list(ConfigKey::TRIGGER_MATCH); + } catch (Error e) { return; + } _trigger_bar = new QToolBar(parent); init_trigger_actions(_trigger_bar); _trigger_bar->addAction(_trigger_none); - trig_matches = (const int32_t *)g_variant_get_fixed_array(gvar, - &num_opts, sizeof(int32_t)); - for (i = 0; i < num_opts; i++) { - _trigger_bar->addAction(match_action(trig_matches[i])); - is_checked = _trigger_match == trig_matches[i]; - match_action(trig_matches[i])->setChecked(is_checked); + trig_types = + Glib::VariantBase::cast_dynamic>>( + gvar).get(); + for (auto type_id : trig_types) { + auto type = TriggerMatchType::get(type_id); + _trigger_bar->addAction(match_action(type)); + is_checked = _trigger_match == type; + match_action(type)->setChecked(is_checked); } form->addRow(tr("Trigger"), _trigger_bar); - g_variant_unref(gvar); } diff --git a/pv/view/logicsignal.h b/pv/view/logicsignal.h index 0f6714cf..11b1d2bd 100644 --- a/pv/view/logicsignal.h +++ b/pv/view/logicsignal.h @@ -27,6 +27,11 @@ class QToolBar; +namespace sigrok { + class Device; + class TriggerMatchType; +} + namespace pv { namespace data { @@ -49,8 +54,8 @@ private: static const QColor SignalColours[10]; public: - LogicSignal(std::shared_ptr dev_inst, - const sr_channel *const channel, + LogicSignal(std::shared_ptr device, + std::shared_ptr channel, std::shared_ptr data); virtual ~LogicSignal(); @@ -83,17 +88,18 @@ private: void init_trigger_actions(QWidget *parent); - QAction* match_action(int match); - int action_match(QAction *action); + QAction* match_action(const sigrok::TriggerMatchType *match); + const sigrok::TriggerMatchType *action_match(QAction *action); void populate_popup_form(QWidget *parent, QFormLayout *form); private Q_SLOTS: void on_trigger(); private: + std::shared_ptr _device; std::shared_ptr _data; - int _trigger_match; + const sigrok::TriggerMatchType *_trigger_match; QToolBar *_trigger_bar; QAction *_trigger_none; QAction *_trigger_rising; diff --git a/pv/view/signal.cpp b/pv/view/signal.cpp index 7df31767..16ebc74d 100644 --- a/pv/view/signal.cpp +++ b/pv/view/signal.cpp @@ -29,15 +29,15 @@ #include #include -#include +#include #include "signal.h" #include "view.h" -#include - using std::shared_ptr; +using sigrok::Channel; + namespace pv { namespace view { @@ -58,10 +58,8 @@ const char *const ChannelNames[] = { "SCL" }; -Signal::Signal(shared_ptr dev_inst, - const sr_channel *const channel) : - Trace(channel->name), - _dev_inst(dev_inst), +Signal::Signal(shared_ptr channel) : + Trace(channel->name().c_str()), _channel(channel), _name_widget(NULL), _updating_name_widget(false) @@ -79,16 +77,16 @@ void Signal::set_name(QString name) bool Signal::enabled() const { - return _channel->enabled; + return _channel->enabled(); } void Signal::enable(bool enable) { - _dev_inst->enable_channel(_channel, enable); + _channel->set_enabled(enable); visibility_changed(); } -const sr_channel* Signal::channel() const +shared_ptr Signal::channel() const { return _channel; } diff --git a/pv/view/signal.h b/pv/view/signal.h index cce9f469..7028b29e 100644 --- a/pv/view/signal.h +++ b/pv/view/signal.h @@ -30,7 +30,9 @@ #include "trace.h" -struct sr_channel; +namespace sigrok { + class Channel; +} namespace pv { @@ -38,10 +40,6 @@ namespace data { class SignalData; } -namespace device { -class DevInst; -} - namespace view { class Signal : public Trace @@ -49,8 +47,7 @@ class Signal : public Trace Q_OBJECT protected: - Signal(std::shared_ptr dev_inst, - const sr_channel *const channel); + Signal(std::shared_ptr channel); public: /** @@ -67,7 +64,7 @@ public: void enable(bool enable = true); - const sr_channel* channel() const; + std::shared_ptr channel() const; virtual void populate_popup_form(QWidget *parent, QFormLayout *form); @@ -79,8 +76,7 @@ private Q_SLOTS: void on_disable(); protected: - std::shared_ptr _dev_inst; - const sr_channel *const _channel; + std::shared_ptr _channel; QComboBox *_name_widget; bool _updating_name_widget;