fwt_software/src/core/CameraProfile.cpp

81 lines
3.0 KiB
C++

#include "fgc/CameraProfile.h"
#include "fgc/Hash.h"
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <stdexcept>
namespace fs = std::filesystem;
namespace fgc {
CameraProfile loadCameraProfile(const std::string& profile_dir, const std::string& name,
ProfileLoadResult& result) {
result = {};
CameraProfile p;
p.name = name;
p.xml_path = (fs::path(profile_dir) / (name + ".xml")).string();
p.txt_path = (fs::path(profile_dir) / (name + ".txt")).string();
if (!fs::is_regular_file(p.xml_path))
throw std::runtime_error("camera profile '" + name + "': " + p.xml_path +
" not found (export it from the VimbaX Viewer)");
const std::string label = hashLabel(fnv1a64File(p.xml_path));
p.settings = parseCameraSettingsXml(p.xml_path);
// An absent or stale record is regenerated. Reading the old one first is what
// lets the caller report WHICH settings moved, rather than just that the file
// changed - that difference is the whole value of the check.
const SettingsRecord old = readSettingsRecord(p.txt_path);
if (old.hash_label == label) return p;
result.regenerated = true;
// No previous record means no baseline, not 800 changed settings.
result.first_run = old.hash_label.empty() && old.entries.empty();
if (!result.first_run) result.changes = diffSettings(old.entries, p.settings.entries);
const std::string xml_name = fs::path(p.xml_path).filename().string();
std::ofstream out(p.txt_path, std::ios::binary | std::ios::trunc);
if (!out)
throw std::runtime_error("camera profile '" + name + "': cannot write the settings "
"record " + p.txt_path);
out << renderSettingsRecord(p.settings, xml_name, label);
if (!out)
throw std::runtime_error("camera profile '" + name + "': failed writing " + p.txt_path);
return p;
}
std::map<std::string, CameraProfile> loadCameraProfiles(
const std::string& dir, std::map<std::string, ProfileLoadResult>& results) {
results.clear();
std::error_code ec;
if (!fs::is_directory(dir, ec))
throw std::runtime_error("camera profile directory not found: " + dir);
// Sorted so startup logs and the UI list profiles in a stable order.
std::vector<std::string> names;
for (const auto& entry : fs::directory_iterator(dir, ec))
if (entry.is_regular_file() && entry.path().extension() == ".xml")
names.push_back(entry.path().stem().string());
std::sort(names.begin(), names.end());
std::map<std::string, CameraProfile> out;
for (const auto& n : names) {
ProfileLoadResult r;
out.emplace(n, loadCameraProfile(dir, n, r));
if (r.regenerated) results.emplace(n, std::move(r));
}
if (out.empty())
throw std::runtime_error("no camera profiles (*.xml) in " + dir +
" (export them from the VimbaX Viewer)");
return out;
}
} // namespace fgc