]> sigrok.org Git - pulseview.git/blobdiff - pv/devicemanager.cpp
DeviceManager: Introduce full device names
[pulseview.git] / pv / devicemanager.cpp
index 4c9f768a909a07e1585c84d9c0785c2c7b92d6e8..df0b055caa7dc849a5fa12b1278edeba8e6cb270 100644 (file)
@@ -18,8 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-#include "devicemanager.h"
-#include "sigsession.h"
+#include "devicemanager.hpp"
+#include "session.hpp"
 
 #include <cassert>
 #include <stdexcept>
@@ -53,7 +53,7 @@ using sigrok::SessionDevice;
 namespace pv {
 
 DeviceManager::DeviceManager(shared_ptr<Context> context) :
-       _context(context)
+       context_(context)
 {
        for (auto entry : context->drivers())
                driver_scan(entry.second, map<const ConfigKey *, VariantBase>());
@@ -65,12 +65,12 @@ DeviceManager::~DeviceManager()
 
 shared_ptr<Context> DeviceManager::context()
 {
-       return _context;
+       return context_;
 }
 
 const list< shared_ptr<HardwareDevice> >& DeviceManager::devices() const
 {
-       return _devices;
+       return devices_;
 }
 
 list< shared_ptr<HardwareDevice> > DeviceManager::driver_scan(
@@ -82,18 +82,32 @@ list< shared_ptr<HardwareDevice> > DeviceManager::driver_scan(
 
        // Remove any device instances from this driver from the device
        // list. They will not be valid after the scan.
-       _devices.remove_if([&](shared_ptr<HardwareDevice> device) {
+       devices_.remove_if([&](shared_ptr<HardwareDevice> device) {
                return device->driver() == driver; });
 
        // Do the scan
        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
-       _devices.insert(_devices.end(), driver_devices.begin(),
+       // Add the scanned devices to the main list, set display names and sort.
+       devices_.insert(devices_.end(), driver_devices.begin(),
                driver_devices.end());
-       _devices.sort(compare_devices);
+
+       for (shared_ptr<Device> device : devices_)
+               build_display_name(device);
+
+       devices_.sort([&](shared_ptr<Device> a, shared_ptr<Device> b)
+               { return compare_devices(a, b); });
+
+       // As the display names depend on the complete devices_ list,
+       // we need to recompute them. However, there is no need to
+       // recomute all names of the devices_ list since only the
+       // devices that use the given driver can be affected.
+       for (shared_ptr<Device> device : driver_devices)
+               build_display_name(device);
+
+       driver_devices.sort([&](shared_ptr<Device> a, shared_ptr<Device> b)
+               { return compare_devices(a, b); });
 
        return driver_devices;
 }
@@ -127,7 +141,7 @@ const shared_ptr<HardwareDevice> DeviceManager::find_device_from_info(
 
        last_resort_dev = NULL;
 
-       for (shared_ptr<HardwareDevice> dev : _devices) {
+       for (shared_ptr<HardwareDevice> dev : devices_) {
                assert(dev);
                dev_info = get_device_info(dev);
 
@@ -170,19 +184,66 @@ const shared_ptr<HardwareDevice> DeviceManager::find_device_from_info(
        return last_resort_dev;
 }
 
-string DeviceManager::device_description(shared_ptr<Device> device)
+void DeviceManager::build_display_name(shared_ptr<Device> device)
 {
        auto session_device = dynamic_pointer_cast<SessionDevice>(device);
+       auto hardware_device = dynamic_pointer_cast<HardwareDevice>(device);
 
-       if (session_device)
-               return boost::filesystem::path(
+       if (session_device) {
+               full_names_[device] = display_names_[device] =
+                       boost::filesystem::path(
                        session_device->parent()->filename()).filename().string();
+               return;
+       }
 
        ostringstream s;
 
+       // First, build the device's full name. It always contains all
+       // possible information.
        vector<string> parts = {device->vendor(), device->model(),
                device->version(), device->serial_number()};
 
+       if (device->connection_id().length() > 0)
+               parts.push_back("("+device->connection_id()+")");
+
+       for (size_t i = 0; i < parts.size(); i++)
+       {
+               if (parts[i].length() > 0)
+               {
+                       if (i != 0)
+                               s << " ";
+                       s << parts[i];
+               }
+       }
+
+       full_names_[device] = s.str();
+
+       // Next, build the display name. It only contains fields as required.
+       bool multiple_dev = false;
+
+       // If we can find another device with the same model/vendor then
+       // we have at least two such devices and need to distinguish them.
+       if (hardware_device)
+               multiple_dev = any_of(devices_.begin(), devices_.end(),
+                       [&](shared_ptr<HardwareDevice> dev) {
+                       return (dev->vendor() == hardware_device->vendor() &&
+                       dev->model() == hardware_device->model()) &&
+                       dev != hardware_device;
+                       } );
+
+       s.str("");
+       parts.clear();
+       parts = {device->vendor(), device->model()};
+
+       if (multiple_dev) {
+               parts.push_back(device->version());
+               parts.push_back(device->serial_number());
+
+               if ((device->serial_number().length() == 0) &&
+                       (device->connection_id().length() > 0))
+                       parts.push_back("("+device->connection_id()+")");
+       }
+
        for (size_t i = 0; i < parts.size(); i++)
        {
                if (parts[i].length() > 0)
@@ -193,20 +254,31 @@ string DeviceManager::device_description(shared_ptr<Device> device)
                }
        }
 
-       if (device->serial_number().length() == 0 &&
-                       device->connection_id().length() > 0)
-               s << " " << device->connection_id();
+       display_names_[device] = s.str();
+}
+
+const std::string DeviceManager::get_display_name(std::shared_ptr<sigrok::Device> dev)
+{
+       return display_names_[dev];
+}
 
-       return s.str();
+const std::string DeviceManager::get_full_name(std::shared_ptr<sigrok::Device> dev)
+{
+       return full_names_[dev];
+}
+
+void DeviceManager::update_display_name(std::shared_ptr<sigrok::Device> dev)
+{
+       build_display_name(dev);
 }
 
-bool DeviceManager::compare_devices(shared_ptr<HardwareDevice> a,
-       shared_ptr<HardwareDevice> b)
+bool DeviceManager::compare_devices(shared_ptr<Device> a,
+       shared_ptr<Device> b)
 {
        assert(a);
        assert(b);
 
-       return device_description(a).compare(device_description(b)) < 0;
+       return display_names_[a].compare(display_names_[b]) < 0;
 }
 
 } // namespace pv