From 2c4aa5155204afb0778618ea35c3847d7054bb77 Mon Sep 17 00:00:00 2001
From: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Date: Wed, 9 Jul 2014 17:08:55 -0400
Subject: [PATCH] video_device_monitor: restore preferences

Rework the way preferences are stored and restored to a device, when
they are unserialized or when a new device is added.

rationales:

  * getters should not modify a device.
  * when unserializing preferences:
    - reset the corresponding device, if it is present.
    - assign the default to the first preference, or the first plugged.
  * when adding a device:
    - reset its preferences (if any) or store them.
    - assign it as default, if there's no default yet.

Issue: #51243
Change-Id: I5423e43f988cf9b7240dd1271cdf5e5b7f79bfce
---
 daemon/src/video/video_device_monitor.cpp | 86 +++++++++++++----------
 daemon/src/video/video_device_monitor.h   |  2 +-
 2 files changed, 48 insertions(+), 40 deletions(-)

diff --git a/daemon/src/video/video_device_monitor.cpp b/daemon/src/video/video_device_monitor.cpp
index 0d11e5198e..ee0bfb0eaa 100644
--- a/daemon/src/video/video_device_monitor.cpp
+++ b/daemon/src/video/video_device_monitor.cpp
@@ -77,14 +77,6 @@ VideoDeviceMonitor::getSettings(const string& name)
     if (itd == devices_.end())
         return VideoSettings();
 
-    /*
-     * Unserialization of device preferences is done after plugged devices were
-     * added. If preferences are stored for this device, apply them first.
-     */
-    auto itp = findPreferencesByName(name);
-    if (itp != preferences_.end())
-        itd->applySettings(*itp);
-
     return itd->getSettings();
 }
 
@@ -97,7 +89,7 @@ VideoDeviceMonitor::applySettings(const string& name, VideoSettings settings)
         return;
 
     iter->applySettings(settings);
-    storePreferences(iter->getSettings());
+    overwritePreferences(iter->getSettings());
 }
 
 string
@@ -173,9 +165,21 @@ VideoDeviceMonitor::addDevice(const string& node)
     if (findDeviceByNode(node) != devices_.end())
         return;
 
+    // instantiate a new unique device
     VideoDevice dev(node);
     giveUniqueName(dev, devices_);
 
+    // restore its preferences if any, or store the defaults
+    auto it = findPreferencesByName(dev.name);
+    if (it != preferences_.end())
+        dev.applySettings(*it);
+    else
+        preferences_.push_back(dev.getSettings());
+
+    // in case there is no default device on a fresh run
+    if (defaultDevice_.empty())
+        defaultDevice_ = dev.name;
+
     devices_.push_back(dev);
     notify();
 }
@@ -256,7 +260,7 @@ VideoDeviceMonitor::findPreferencesByName(const string& name)
 }
 
 void
-VideoDeviceMonitor::storePreferences(VideoSettings settings)
+VideoDeviceMonitor::overwritePreferences(VideoSettings settings)
 {
     auto it = findPreferencesByName(settings["name"]);
     if (it != preferences_.end())
@@ -305,37 +309,41 @@ VideoDeviceMonitor::unserialize(const Conf::YamlNode &node)
 
     if (!devicesNode || devicesNode->getType() != SEQUENCE) {
         ERROR("No 'devices' sequence node! Old config?");
-    } else {
-        SequenceNode *seqNode = static_cast<SequenceNode *>(devicesNode);
-        Sequence *seq = seqNode->getSequence();
-
-        if (seq->empty()) {
-            WARN("Empty video device list");
-        } else {
-            for (const auto &iter : *seq) {
-                MappingNode *devnode = static_cast<MappingNode *>(iter);
-                VideoSettings pref;
-
-                devnode->getValue("name", &pref["name"]);
-                devnode->getValue("channel", &pref["channel"]);
-                devnode->getValue("size", &pref["size"]);
-                devnode->getValue("rate", &pref["rate"]);
-
-                storePreferences(pref);
-
-                // Update the default device if it is plugged
-                if (defaultDevice_.empty()) {
-                    auto it = findDeviceByName(pref["name"]);
-                    if (it != devices_.end())
-                        defaultDevice_ = it->name;
-                }
-            }
+        return;
+    }
 
-            // If no default device, use to the first plugged one
-            if (defaultDevice_.empty() && !devices_.empty())
-                defaultDevice_ = devices_[0].name;
-        }
+    SequenceNode *seqNode = static_cast<SequenceNode *>(devicesNode);
+    Sequence *seq = seqNode->getSequence();
+
+    if (seq->empty()) {
+        WARN("Empty video device list");
+        return;
+    }
+
+    for (const auto &iter : *seq) {
+        MappingNode *devnode = static_cast<MappingNode *>(iter);
+        VideoSettings pref;
+
+        devnode->getValue("name", &pref["name"]);
+        devnode->getValue("channel", &pref["channel"]);
+        devnode->getValue("size", &pref["size"]);
+        devnode->getValue("rate", &pref["rate"]);
+
+        overwritePreferences(pref);
+
+        // Restore the device preferences if present
+        auto itd = findDeviceByName(pref["name"]);
+        if (itd != devices_.end())
+            itd->applySettings(pref);
     }
+
+    // Restore the default device if present, or select the first one
+    const string pref = preferences_.empty() ? "" : preferences_[0]["name"];
+    const string first = devices_.empty() ? "" : devices_[0].name;
+    if (findDeviceByName(pref) != devices_.end())
+        defaultDevice_ = pref;
+    else
+        defaultDevice_ = first;
 }
 
 } // namespace sfl_video
diff --git a/daemon/src/video/video_device_monitor.h b/daemon/src/video/video_device_monitor.h
index e3ebb7a4a2..cd4e98db7c 100644
--- a/daemon/src/video/video_device_monitor.h
+++ b/daemon/src/video/video_device_monitor.h
@@ -82,7 +82,7 @@ class VideoDeviceMonitor : public Serializable
          */
         std::vector<VideoSettings> preferences_;
 
-        void storePreferences(VideoSettings settings);
+        void overwritePreferences(VideoSettings settings);
         std::vector<VideoSettings>::iterator findPreferencesByName(const std::string& name);
 
         /*
-- 
GitLab