From 79181d1484af5ecdc8a7d8037a123ccc74fca559 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 30 Dec 2021 12:09:04 +0100 Subject: [PATCH] Add model files loading for B&W radios --- .../src/firmwares/edgetx/edgetxinterface.cpp | 7 +- .../src/firmwares/edgetx/edgetxinterface.h | 1 + companion/src/storage/categorized.cpp | 86 +++++++++++-------- companion/src/storage/categorized.h | 3 + companion/src/storage/etx.cpp | 15 ++++ companion/src/storage/etx.h | 1 + companion/src/storage/otx.h | 1 + companion/src/storage/sdcard.cpp | 10 +++ companion/src/storage/sdcard.h | 1 + 9 files changed, 85 insertions(+), 40 deletions(-) diff --git a/companion/src/firmwares/edgetx/edgetxinterface.cpp b/companion/src/firmwares/edgetx/edgetxinterface.cpp index d5a90de1f..49e205107 100644 --- a/companion/src/firmwares/edgetx/edgetxinterface.cpp +++ b/companion/src/firmwares/edgetx/edgetxinterface.cpp @@ -52,6 +52,7 @@ bool loadModelsListFromYaml(std::vector& categories, YAML::Node node = loadYamlFromByteArray(data); if (!node.IsSequence()) return false; + int modelIdx = 0; for (const auto& cat : node) { if (!cat.IsMap()) continue; @@ -63,11 +64,11 @@ bool loadModelsListFromYaml(std::vector& categories, if (!models.IsSequence()) continue; for (const auto& model : models) { - std::string filename; + std::string filename, name; model["filename"] >> filename; - std::string name; model["name"] >> name; - modelFiles.push_back({filename, name, (int)categories.size() - 1}); + modelFiles.push_back( + {filename, name, (int)categories.size() - 1, modelIdx++}); } } } diff --git a/companion/src/firmwares/edgetx/edgetxinterface.h b/companion/src/firmwares/edgetx/edgetxinterface.h index 4512ccd8d..55b374ac9 100644 --- a/companion/src/firmwares/edgetx/edgetxinterface.h +++ b/companion/src/firmwares/edgetx/edgetxinterface.h @@ -33,6 +33,7 @@ struct EtxModelMetadata { std::string filename; std::string name; int category; + int modelIdx; }; typedef std::list EtxModelfiles; diff --git a/companion/src/storage/categorized.cpp b/companion/src/storage/categorized.cpp index b5745d51f..7eb8af901 100644 --- a/companion/src/storage/categorized.cpp +++ b/companion/src/storage/categorized.cpp @@ -23,6 +23,8 @@ #include "firmwares/edgetx/edgetxinterface.h" #include "miniz.c" // Can only be included once! +#include + bool CategorizedStorageFormat::load(RadioData & radioData) { StorageType st = getStorageType(filename); @@ -243,50 +245,63 @@ bool CategorizedStorageFormat::loadYaml(RadioData & radioData) board = (Board::Type)radioData.generalSettings.variant; // get models + EtxModelfiles modelFiles; + QByteArray modelslistBuffer; if (loadFile(modelslistBuffer, "MODELS/models.yml")) { - // List< { filename, category index } > - EtxModelfiles modelFiles; if (!loadModelsListFromYaml(radioData.categories, modelFiles, modelslistBuffer)) { setError(tr("Can't load MODELS/models.yml")); return false; } - - radioData.models.resize(modelFiles.size()); - - int modelIdx = 0; - for (const auto& mc : modelFiles) { - qDebug() << "Filename: " << mc.filename.c_str() << " / Category: " << mc.category; - - QByteArray modelBuffer; - QString filename = "MODELS/" + QString::fromStdString(mc.filename); - if (!loadFile(modelBuffer, filename)) { - setError(tr("Can't extract ") + filename); - return false; - } - - // Please note: - // ModelData() use memset to clear everything to 0 - // - auto& model = radioData.models[modelIdx]; - - if (!loadModelFromYaml(model,modelBuffer)) { - setError(tr("Can't load ") + filename); - return false; - } - - model.category = mc.category; - model.modelIndex = modelIdx; - strncpy(model.filename, mc.filename.c_str(), sizeof(model.filename)-1); - - model.used = true; - modelIdx++; - } - } else { // fetch "MODELS/modelXX.yml" + std::list filelist; + if (!getFileList(filelist)) { + setError(tr("Can't list files")); + return false; + } + + const std::regex yml_regex("MODELS/(model([0-9]+)\\.yml)"); + for(const auto& f : filelist) { + std::smatch match; + if (std::regex_match(f, match, yml_regex)) { + if (match.size() == 3) { + std::ssub_match modelFile = match[1]; + std::ssub_match modelIdx = match[2]; + modelFiles.push_back({ modelFile.str(), "", 0, std::stoi(modelIdx.str()) }); + } + } + } + } + + radioData.models.resize(modelFiles.size()); + for (const auto& mc : modelFiles) { + qDebug() << "Filename: " << mc.filename.c_str() << " / Category: " << mc.category; + + QByteArray modelBuffer; + QString filename = "MODELS/" + QString::fromStdString(mc.filename); + if (!loadFile(modelBuffer, filename)) { + setError(tr("Can't extract ") + filename); + return false; + } + + // Please note: + // ModelData() use memset to clear everything to 0 + // + auto& model = radioData.models[mc.modelIdx]; + + if (!loadModelFromYaml(model,modelBuffer)) { + setError(tr("Can't load ") + filename); + return false; + } + + model.category = mc.category; + model.modelIndex = mc.modelIdx; + strncpy(model.filename, mc.filename.c_str(), sizeof(model.filename)-1); + + model.used = true; } return true; @@ -308,12 +323,9 @@ bool CategorizedStorageFormat::writeYaml(const RadioData & radioData) EtxModelfiles modelFiles; for (const auto& model : radioData.models) { - qDebug() << "Model index: " << model.modelIndex; if (model.isEmpty()) continue; - // TODO: verify '.yml' (in case we moved from '.bin') - QString modelFilename; if (hasCategories) { std::string ymlFilename = patchFilenameToYaml(model.filename); diff --git a/companion/src/storage/categorized.h b/companion/src/storage/categorized.h index df9f069c9..c14769d27 100644 --- a/companion/src/storage/categorized.h +++ b/companion/src/storage/categorized.h @@ -24,6 +24,8 @@ #include "storage.h" #include +#include +#include class CategorizedStorageFormat : public StorageFormat { @@ -41,6 +43,7 @@ class CategorizedStorageFormat : public StorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName) = 0; virtual bool writeFile(const QByteArray & fileData, const QString & fileName) = 0; + virtual bool getFileList(std::list& filelist) = 0; virtual bool loadBin(RadioData & radioData); virtual bool writeBin(const RadioData & radioData); diff --git a/companion/src/storage/etx.cpp b/companion/src/storage/etx.cpp index 051bf8391..8ec2085ef 100644 --- a/companion/src/storage/etx.cpp +++ b/companion/src/storage/etx.cpp @@ -113,3 +113,18 @@ bool EtxFormat::writeFile(const QByteArray & filedata, const QString & filename) return true; } + +bool EtxFormat::getFileList(std::list& filelist) +{ + int count = (int)mz_zip_reader_get_num_files(&zip_archive); + if (count == 0) return false; + + mz_zip_archive_file_stat file_stat; + for (int i=0; i& filelist); mz_zip_archive zip_archive; }; diff --git a/companion/src/storage/otx.h b/companion/src/storage/otx.h index da4923488..37739074c 100644 --- a/companion/src/storage/otx.h +++ b/companion/src/storage/otx.h @@ -46,6 +46,7 @@ class OtxFormat : public CategorizedStorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName); virtual bool writeFile(const QByteArray & fileData, const QString & fileName); + virtual bool getFileList(std::list& filelist) { return false; } mz_zip_archive zip_archive; }; diff --git a/companion/src/storage/sdcard.cpp b/companion/src/storage/sdcard.cpp index 248f23615..3ac02f1fd 100644 --- a/companion/src/storage/sdcard.cpp +++ b/companion/src/storage/sdcard.cpp @@ -57,6 +57,16 @@ bool SdcardFormat::writeFile(const QByteArray & data, const QString & filename) return true; } +bool SdcardFormat::getFileList(std::list& filelist) +{ + QDir dir(filename); + QStringList ql = dir.entryList(); + for (const auto& str : ql) { + filelist.push_back(str.toStdString()); + } + return true; +} + bool SdcardStorageFactory::probe(const QString & path) { return QDir(path).exists(); diff --git a/companion/src/storage/sdcard.h b/companion/src/storage/sdcard.h index 1d7d813d2..cc6230a9b 100644 --- a/companion/src/storage/sdcard.h +++ b/companion/src/storage/sdcard.h @@ -41,6 +41,7 @@ class SdcardFormat : public CategorizedStorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName); virtual bool writeFile(const QByteArray & fileData, const QString & fileName); + virtual bool getFileList(std::list& filelist); }; class SdcardStorageFactory : public DefaultStorageFactory