mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Crudely bodge image writes into working.
This commit is contained in:
@@ -451,6 +451,29 @@ bool Config::applyOption(const std::string& name, const std::string value)
|
||||
return optionInfo.usesValue;
|
||||
}
|
||||
|
||||
void Config::applyOptionsFile(const std::string& data)
|
||||
{
|
||||
if (!data.empty())
|
||||
{
|
||||
for (auto setting : split(data, '\n'))
|
||||
{
|
||||
setting = trimWhitespace(setting);
|
||||
if (setting.size() == 0)
|
||||
continue;
|
||||
if (setting[0] == '#')
|
||||
continue;
|
||||
|
||||
auto equals = setting.find('=');
|
||||
if (equals == std::string::npos)
|
||||
error("Malformed setting line '{}'", setting);
|
||||
|
||||
auto key = setting.substr(0, equals);
|
||||
auto value = setting.substr(equals + 1);
|
||||
globalConfig().set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::applyDefaultOptions()
|
||||
{
|
||||
std::set<const OptionGroupProto*> appliedOptionGroups;
|
||||
|
||||
@@ -142,6 +142,7 @@ public:
|
||||
bool isOptionValid(const OptionProto& option);
|
||||
void applyOption(const OptionInfo& optionInfo);
|
||||
bool applyOption(const std::string& name, const std::string value = "");
|
||||
void applyOptionsFile(const std::string& data);
|
||||
void applyDefaultOptions();
|
||||
void clearOptions();
|
||||
|
||||
|
||||
@@ -540,12 +540,13 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor)
|
||||
return fields;
|
||||
}
|
||||
|
||||
std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
|
||||
std::vector<ProtoField> findAllProtoFields(
|
||||
const google::protobuf::Message* message)
|
||||
{
|
||||
std::vector<ProtoField> allFields;
|
||||
|
||||
std::function<void(google::protobuf::Message*, const std::string&)>
|
||||
recurse = [&](auto* message, const auto& name)
|
||||
std::function<void(const google::protobuf::Message*, const std::string&)>
|
||||
recurse = [&](const auto* message, const auto& name)
|
||||
{
|
||||
const auto* reflection = message->GetReflection();
|
||||
std::vector<const google::protobuf::FieldDescriptor*> fields;
|
||||
@@ -565,18 +566,19 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
|
||||
const auto n = fmt::format("{}[{}]", basename, i);
|
||||
if (shouldRecurse(f))
|
||||
recurse(
|
||||
reflection->MutableRepeatedMessage(message, f, i),
|
||||
n);
|
||||
&reflection->GetRepeatedMessage(*message, f, i), n);
|
||||
else
|
||||
allFields.push_back(ProtoField(n, message, f, i));
|
||||
allFields.push_back(ProtoField(
|
||||
n, (google::protobuf::Message*)message, f, i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shouldRecurse(f))
|
||||
recurse(reflection->MutableMessage(message, f), basename);
|
||||
recurse(&reflection->GetMessage(*message, f), basename);
|
||||
else
|
||||
allFields.push_back(ProtoField(basename, message, f));
|
||||
allFields.push_back(ProtoField(
|
||||
basename, (google::protobuf::Message*)message, f));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -584,3 +586,12 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
|
||||
recurse(message, "");
|
||||
return allFields;
|
||||
}
|
||||
|
||||
std::string renderProtoAsConfig(const google::protobuf::Message* message)
|
||||
{
|
||||
auto allFields = findAllProtoFields(message);
|
||||
std::stringstream ss;
|
||||
for (const auto& field : allFields)
|
||||
ss << field.path() << "=" << field.get() << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,9 @@ extern std::map<std::string, const google::protobuf::FieldDescriptor*>
|
||||
findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor);
|
||||
|
||||
extern std::vector<ProtoField> findAllProtoFields(
|
||||
google::protobuf::Message* message);
|
||||
const google::protobuf::Message* message);
|
||||
extern std::string renderProtoAsConfig(
|
||||
const google::protobuf::Message* message);
|
||||
|
||||
template <class T>
|
||||
static inline const T parseProtoBytes(const std::string_view& bytes)
|
||||
|
||||
@@ -11,9 +11,7 @@ std::unique_ptr<FluxSource> FluxSource::create(Config& config)
|
||||
{
|
||||
if (!config.hasFluxSource())
|
||||
error("no flux source configured");
|
||||
auto fluxSource = create(config->flux_source());
|
||||
globalConfig().base()->MergeFrom(fluxSource->getExtraConfig());
|
||||
return fluxSource;
|
||||
return create(config->flux_source());
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::create(const FluxSourceProto& config)
|
||||
|
||||
@@ -111,6 +111,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_extraConfig.mutable_layout()->add_layoutdata()->set_sector_size(524);
|
||||
|
||||
image->setGeometry({.numCylinders = numCylinders,
|
||||
.numHeads = numHeads,
|
||||
.numSectors = 12,
|
||||
|
||||
@@ -54,6 +54,7 @@ int mainWrite(int argc, const char* argv[])
|
||||
|
||||
auto reader = ImageReader::create(globalConfig());
|
||||
std::shared_ptr<Image> image = reader->readImage();
|
||||
globalConfig().overrides()->MergeFrom(reader->getExtraConfig());
|
||||
|
||||
auto diskLayout = createDiskLayout();
|
||||
auto encoder = Arch::createEncoder(globalConfig());
|
||||
|
||||
@@ -18,9 +18,25 @@ using namespace hex;
|
||||
|
||||
static DynamicSettingFactory settings("fluxengine.settings");
|
||||
|
||||
static constexpr const char* DEFAULT_CUSTOM_SETTINGS = R"R(
|
||||
# These settings will override the ones above.
|
||||
# Here are some useful ones:
|
||||
# decoder.retries=0
|
||||
# drive.revolutions=1.2
|
||||
)R";
|
||||
|
||||
ConfigView::ConfigView():
|
||||
View::Window("fluxengine.view.config.name", ICON_VS_COMPASS)
|
||||
{
|
||||
Events::SetSystemConfig::subscribe(
|
||||
[](std::string customConfig)
|
||||
{
|
||||
auto customSetting = settings.get<std::string>("systemProperties");
|
||||
customSetting =
|
||||
"# These settings were set by a file and\n"
|
||||
"# may contradict the ones above (it's a bug).\n" +
|
||||
customConfig;
|
||||
});
|
||||
}
|
||||
|
||||
static void emitOptions(DynamicSetting<std::string>& setting,
|
||||
@@ -336,11 +352,33 @@ void ConfigView::drawContent()
|
||||
|
||||
ImGui::SeparatorText("fluxengine.view.config.customProperties"_lang);
|
||||
|
||||
auto customSetting = settings.get<std::string>("custom");
|
||||
std::string buffer = customSetting;
|
||||
if (ImGui::InputTextMultiline("##customProperties",
|
||||
buffer,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiInputTextFlags_None))
|
||||
customSetting = buffer;
|
||||
if (ImGui::BeginTabBar("customconfig", ImGuiTabBarFlags_None))
|
||||
{
|
||||
DEFER(ImGui::EndTabBar());
|
||||
if (ImGui::BeginTabItem("User"))
|
||||
{
|
||||
DEFER(ImGui::EndTabItem());
|
||||
|
||||
auto setting =
|
||||
settings.get<std::string>("custom", DEFAULT_CUSTOM_SETTINGS);
|
||||
std::string buffer = setting;
|
||||
if (ImGui::InputTextMultiline("##customProperties",
|
||||
buffer,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiInputTextFlags_None))
|
||||
setting = buffer;
|
||||
}
|
||||
if (ImGui::BeginTabItem("System"))
|
||||
{
|
||||
DEFER(ImGui::EndTabItem());
|
||||
|
||||
auto setting = settings.get<std::string>("systemProperties");
|
||||
std::string buffer = setting;
|
||||
if (ImGui::InputTextMultiline("##systemProperties",
|
||||
buffer,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiInputTextFlags_None))
|
||||
setting = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "lib/core/globals.h"
|
||||
#include "lib/core/utils.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/config/proto.h"
|
||||
#include "lib/data/disk.h"
|
||||
#include "lib/data/image.h"
|
||||
#include "lib/fluxsource/fluxsource.h"
|
||||
@@ -50,7 +51,7 @@ static bool formattingSupported;
|
||||
static std::map<std::string, Datastore::Device> devices;
|
||||
static std::shared_ptr<const DiskLayout> diskLayout;
|
||||
|
||||
static void wtRebuildConfiguration();
|
||||
static void wtRebuildConfiguration(bool useCustom);
|
||||
|
||||
static void workerThread_cb()
|
||||
{
|
||||
@@ -271,7 +272,11 @@ void Datastore::init()
|
||||
hex::Region{startOffset, endOffset - startOffset});
|
||||
});
|
||||
|
||||
runOnWorkerThread(wtRebuildConfiguration);
|
||||
runOnWorkerThread(
|
||||
[]
|
||||
{
|
||||
wtRebuildConfiguration(true);
|
||||
});
|
||||
}
|
||||
|
||||
bool Datastore::isBusy()
|
||||
@@ -338,7 +343,7 @@ static void wtClearDiskData()
|
||||
});
|
||||
}
|
||||
|
||||
void wtRebuildConfiguration()
|
||||
void wtRebuildConfiguration(bool withCustom = false)
|
||||
{
|
||||
/* Reset and apply the format configuration. */
|
||||
|
||||
@@ -392,26 +397,10 @@ void wtRebuildConfiguration()
|
||||
|
||||
/* Custom settings. */
|
||||
|
||||
auto customSettings = readSettingFromUiThread<std::string>("custom", "");
|
||||
if (!customSettings.empty())
|
||||
{
|
||||
for (auto setting : split(customSettings, '\n'))
|
||||
{
|
||||
setting = trimWhitespace(setting);
|
||||
if (setting.size() == 0)
|
||||
continue;
|
||||
if (setting[0] == '#')
|
||||
continue;
|
||||
|
||||
auto equals = setting.find('=');
|
||||
if (equals == std::string::npos)
|
||||
error("Malformed setting line '{}'", setting);
|
||||
|
||||
auto key = setting.substr(0, equals);
|
||||
auto value = setting.substr(equals + 1);
|
||||
globalConfig().set(key, value);
|
||||
}
|
||||
}
|
||||
globalConfig().applyOptionsFile(
|
||||
readSettingFromUiThread<std::string>("systemProperties", ""));
|
||||
globalConfig().applyOptionsFile(
|
||||
readSettingFromUiThread<std::string>("custom", ""));
|
||||
|
||||
/* Finalise the options. */
|
||||
|
||||
@@ -540,7 +529,7 @@ void Datastore::beginRead(bool rereadBadSectors)
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(true);
|
||||
if (!rereadBadSectors)
|
||||
wtClearDiskData();
|
||||
|
||||
@@ -576,7 +565,7 @@ void Datastore::beginWrite()
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(true);
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
|
||||
auto fluxSinkFactory = FluxSinkFactory::create(globalConfig());
|
||||
@@ -642,7 +631,7 @@ void Datastore::reset()
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(false);
|
||||
wtClearDiskData();
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
}
|
||||
@@ -682,7 +671,7 @@ void Datastore::writeImage(const std::fs::path& path)
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(true);
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
globalConfig().setImageWriter(path.string());
|
||||
ImageWriter::create(globalConfig())
|
||||
@@ -708,11 +697,23 @@ void Datastore::readImage(const std::fs::path& path)
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(true);
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
globalConfig().setImageReader(path.string());
|
||||
std::shared_ptr<Image> image =
|
||||
ImageReader::create(globalConfig())->readImage();
|
||||
auto imageReader = ImageReader::create(globalConfig());
|
||||
std::shared_ptr<Image> image = imageReader->readImage();
|
||||
|
||||
const auto& extraConfig = imageReader->getExtraConfig();
|
||||
auto customConfig = renderProtoAsConfig(&extraConfig);
|
||||
|
||||
/* Update the setting, and then rebuild the config again as it
|
||||
* will have changed. */
|
||||
|
||||
wtRunSynchronouslyOnUiThread((std::function<void()>)[=] {
|
||||
Events::SetSystemConfig::post(customConfig);
|
||||
});
|
||||
wtRebuildConfiguration(true);
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
|
||||
auto disk = wtMakeDiskDataFromImage(image);
|
||||
hex::TaskManager::doLater(
|
||||
@@ -741,7 +742,7 @@ void Datastore::writeFluxFile(const std::fs::path& path)
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(true);
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
|
||||
if (!disk || !disk->image)
|
||||
@@ -777,7 +778,7 @@ void Datastore::createBlankImage()
|
||||
|
||||
try
|
||||
{
|
||||
wtRebuildConfiguration();
|
||||
wtRebuildConfiguration(false);
|
||||
wtClearDiskData();
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
|
||||
@@ -794,6 +795,7 @@ void Datastore::createBlankImage()
|
||||
hex::TaskManager::doLater(
|
||||
[=]
|
||||
{
|
||||
Events::SetSystemConfig::post("");
|
||||
::disk = disk;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Events
|
||||
EVENT_DEF(DiskActivityNotification, DiskActivityType, unsigned, unsigned);
|
||||
EVENT_DEF(OperationStart, std::string);
|
||||
EVENT_DEF(OperationStop, OperationState);
|
||||
EVENT_DEF(SetSystemConfig, std::string);
|
||||
}
|
||||
|
||||
#define DEFER(_stmt) \
|
||||
|
||||
@@ -226,6 +226,49 @@ static void test_findallfields(void)
|
||||
"u64"}));
|
||||
}
|
||||
|
||||
static void test_rendering(void)
|
||||
{
|
||||
std::string s = R"M(
|
||||
i64: -1
|
||||
i32: -2
|
||||
u64: 3
|
||||
u32: 4
|
||||
d: 5.5
|
||||
f: 6.7
|
||||
m {
|
||||
s: "string"
|
||||
}
|
||||
r {
|
||||
s: "val2"
|
||||
}
|
||||
r {
|
||||
s: "val3"
|
||||
}
|
||||
secondoption {
|
||||
s: "2"
|
||||
}
|
||||
)M";
|
||||
|
||||
TestProto proto;
|
||||
if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto))
|
||||
error("couldn't load test proto");
|
||||
|
||||
auto config = renderProtoAsConfig(&proto);
|
||||
|
||||
AssertThat(cleanup(config), Equals(cleanup(R"M(
|
||||
i64=-1
|
||||
i32=-2
|
||||
u64=3
|
||||
u32=4
|
||||
d=5.5
|
||||
m.s=string
|
||||
r[0].s=val2
|
||||
r[1].s=val3
|
||||
secondoption.s=2
|
||||
f=6.7
|
||||
)M")));
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
try
|
||||
@@ -237,6 +280,7 @@ int main(int argc, const char* argv[])
|
||||
test_fields();
|
||||
test_options();
|
||||
test_findallfields();
|
||||
test_rendering();
|
||||
}
|
||||
catch (const ErrorException& e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user