mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Overhaul the log stuff to actually work again (better).
This commit is contained in:
@@ -160,6 +160,16 @@ static const std::vector<ImageConstructor> imageConstructors = {
|
||||
{".xdf", IMAGETYPE_IMG, MODE_RW},
|
||||
};
|
||||
|
||||
struct OptionLogMessage
|
||||
{
|
||||
std::string message;
|
||||
};
|
||||
|
||||
void renderLogMessage(LogRenderer& r, std::shared_ptr<const OptionLogMessage> m)
|
||||
{
|
||||
r.newline().add("OPTION:").add(m->message).newline();
|
||||
}
|
||||
|
||||
Config& globalConfig()
|
||||
{
|
||||
return config;
|
||||
@@ -442,8 +452,8 @@ bool Config::isOptionValid(std::string option)
|
||||
|
||||
void Config::applyOption(const OptionProto& option)
|
||||
{
|
||||
log("OPTION: {}",
|
||||
option.has_message() ? option.message() : option.comment());
|
||||
log(OptionLogMessage{
|
||||
option.has_message() ? option.message() : option.comment()});
|
||||
|
||||
_appliedOptions.insert(option.name());
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ static bool indented = false;
|
||||
static std::function<void(const AnyLogMessage&)> loggerImpl =
|
||||
[](const auto& message)
|
||||
{
|
||||
std::cout << Logger::toString(message) << std::flush;
|
||||
static auto r = LogRenderer::create(std::cout);
|
||||
r->add(message);
|
||||
};
|
||||
|
||||
void log(const char* m)
|
||||
@@ -42,24 +43,14 @@ void renderLogMessage(LogRenderer& r, std::shared_ptr<const std::string> msg)
|
||||
r.newline().add(*msg).newline();
|
||||
}
|
||||
|
||||
std::string Logger::toString(const AnyLogMessage& message)
|
||||
LogRenderer& LogRenderer::add(const AnyLogMessage& message)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
auto indent = [&]()
|
||||
{
|
||||
if (!indented)
|
||||
stream << " ";
|
||||
indented = false;
|
||||
};
|
||||
|
||||
auto r = LogRenderer::create();
|
||||
std::visit(
|
||||
[&](const auto& arg)
|
||||
{
|
||||
renderLogMessage(*r, arg);
|
||||
renderLogMessage(*this, arg);
|
||||
},
|
||||
message);
|
||||
|
||||
return stream.str();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -8,19 +8,7 @@ class DiskFlux;
|
||||
class TrackDataFlux;
|
||||
class TrackFlux;
|
||||
class Sector;
|
||||
|
||||
class LogRenderer
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<LogRenderer> create();
|
||||
|
||||
public:
|
||||
virtual LogRenderer& add(std::string m) = 0;
|
||||
virtual LogRenderer& newsection() = 0;
|
||||
virtual LogRenderer& newline() = 0;
|
||||
|
||||
virtual void renderTo(std::ostream& stream) = 0;
|
||||
};
|
||||
class LogRenderer;
|
||||
|
||||
struct ErrorLogMessage;
|
||||
struct EmergencyStopMessage;
|
||||
@@ -35,6 +23,7 @@ struct EndWriteOperationLogMessage;
|
||||
struct BeginOperationLogMessage;
|
||||
struct EndOperationLogMessage;
|
||||
struct OperationProgressLogMessage;
|
||||
struct OptionLogMessage;
|
||||
|
||||
struct ErrorLogMessage
|
||||
{
|
||||
@@ -71,6 +60,8 @@ extern void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const EndOperationLogMessage> m);
|
||||
extern void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const OperationProgressLogMessage> m);
|
||||
extern void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const OptionLogMessage> m);
|
||||
|
||||
typedef std::variant<std::shared_ptr<const std::string>,
|
||||
std::shared_ptr<const ErrorLogMessage>,
|
||||
@@ -85,7 +76,8 @@ typedef std::variant<std::shared_ptr<const std::string>,
|
||||
std::shared_ptr<const EndWriteOperationLogMessage>,
|
||||
std::shared_ptr<const BeginOperationLogMessage>,
|
||||
std::shared_ptr<const EndOperationLogMessage>,
|
||||
std::shared_ptr<const OperationProgressLogMessage>>
|
||||
std::shared_ptr<const OperationProgressLogMessage>,
|
||||
std::shared_ptr<const OptionLogMessage>>
|
||||
AnyLogMessage;
|
||||
|
||||
extern void log(const char* ptr);
|
||||
@@ -103,11 +95,24 @@ inline void log(fmt::string_view fstr, const Args&... args)
|
||||
log(fmt::format(fstr, args...));
|
||||
}
|
||||
|
||||
class LogRenderer
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<LogRenderer> create(std::ostream& stream);
|
||||
|
||||
public:
|
||||
LogRenderer& add(const AnyLogMessage& message);
|
||||
|
||||
public:
|
||||
virtual LogRenderer& add(const std::string& m) = 0;
|
||||
virtual LogRenderer& comma() = 0;
|
||||
virtual LogRenderer& header(const std::string& h) = 0;
|
||||
virtual LogRenderer& newline() = 0;
|
||||
};
|
||||
|
||||
namespace Logger
|
||||
{
|
||||
extern void setLogger(std::function<void(const AnyLogMessage&)> cb);
|
||||
|
||||
extern std::string toString(const AnyLogMessage&);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,55 +7,89 @@ namespace
|
||||
class LogRendererImpl : public LogRenderer
|
||||
{
|
||||
public:
|
||||
LogRenderer& add(std::string m) override
|
||||
LogRendererImpl(std::ostream& stream): _stream(stream) {}
|
||||
|
||||
private:
|
||||
void indent()
|
||||
{
|
||||
if (_atNewline && _indented)
|
||||
_stream << " ";
|
||||
_lineLen = 7;
|
||||
_space = true;
|
||||
}
|
||||
|
||||
public:
|
||||
LogRenderer& add(const std::string& m) override
|
||||
{
|
||||
if (_newline && !_header)
|
||||
indent();
|
||||
|
||||
if (!_space)
|
||||
{
|
||||
_stream << " ";
|
||||
_lineLen = 4;
|
||||
_indented = true;
|
||||
_stream << ' ';
|
||||
_lineLen++;
|
||||
}
|
||||
|
||||
if ((m.size() + _lineLen) > 80)
|
||||
{
|
||||
_stream << "\n ";
|
||||
_lineLen = 4;
|
||||
_indented = true;
|
||||
}
|
||||
_newline = false;
|
||||
_header = false;
|
||||
|
||||
_lineLen += m.size();
|
||||
if (_lineLen >= 80)
|
||||
{
|
||||
_stream << '\n';
|
||||
indent();
|
||||
}
|
||||
_stream << m;
|
||||
_space = !m.empty() && isspace(m[m.size() - 1]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogRenderer& newsection() override
|
||||
LogRenderer& header(const std::string& m) override
|
||||
{
|
||||
newline();
|
||||
_indented = false;
|
||||
if (!_newline)
|
||||
_stream << '\n';
|
||||
_stream << m;
|
||||
_lineLen = m.size();
|
||||
_header = true;
|
||||
_newline = true;
|
||||
_space = !m.empty() && isspace(m[m.size() - 1]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogRenderer& comma() override
|
||||
{
|
||||
if (!_newline || _header)
|
||||
{
|
||||
_stream << ';';
|
||||
_space = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogRenderer& newline() override
|
||||
{
|
||||
if (!_atNewline)
|
||||
if (!_header)
|
||||
{
|
||||
_stream << '\n';
|
||||
_atNewline = true;
|
||||
if (!_newline)
|
||||
_stream << '\n';
|
||||
|
||||
_lineLen = 0;
|
||||
_header = false;
|
||||
_newline = true;
|
||||
_space = true;
|
||||
}
|
||||
_lineLen = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void renderTo(std::ostream& stream) override {}
|
||||
|
||||
private:
|
||||
bool _atNewline = false;
|
||||
bool _indented = false;
|
||||
bool _header = false;
|
||||
bool _newline = false;
|
||||
bool _space = false;
|
||||
int _lineLen = 0;
|
||||
std::stringstream _stream;
|
||||
std::ostream& _stream;
|
||||
};
|
||||
}
|
||||
|
||||
std::unique_ptr<LogRenderer> LogRenderer::create()
|
||||
std::unique_ptr<LogRenderer> LogRenderer::create(std::ostream& stream)
|
||||
{
|
||||
return std::make_unique<LogRendererImpl>();
|
||||
return std::make_unique<LogRendererImpl>(stream);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ void renderLogMessage(
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginWriteOperationLogMessage> m)
|
||||
{
|
||||
r.newsection().add(fmt::format("{:2}.{}: ", m->track, m->head));
|
||||
r.header(fmt::format("W{:2}.{}: ", m->track, m->head));
|
||||
}
|
||||
|
||||
/* Indicates that we're finishing a write operation. */
|
||||
@@ -70,7 +70,7 @@ void renderLogMessage(
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginReadOperationLogMessage> m)
|
||||
{
|
||||
r.newsection().add(fmt::format("{:2}.{}: ", m->track, m->head));
|
||||
r.header(fmt::format("R{:2}.{}: ", m->track, m->head));
|
||||
}
|
||||
|
||||
/* Indicates that we're finishing a read operation. */
|
||||
@@ -102,13 +102,13 @@ void renderLogMessage(
|
||||
if (!rawSectors.empty())
|
||||
clock /= rawSectors.size();
|
||||
|
||||
r.add(fmt::format("{} raw records, {} raw sectors",
|
||||
r.comma().add(fmt::format("{} raw records, {} raw sectors",
|
||||
rawRecords.size(),
|
||||
rawSectors.size()));
|
||||
if (clock != 0)
|
||||
{
|
||||
r.add(fmt::format(
|
||||
"; {:.2f}us clock ({:.0f}kHz)", clock / 1000.0, 1000000.0 / clock));
|
||||
r.comma().add(fmt::format(
|
||||
"{:.2f}us clock ({:.0f}kHz)", clock / 1000.0, 1000000.0 / clock));
|
||||
}
|
||||
|
||||
r.newline().add("sectors:");
|
||||
@@ -118,7 +118,7 @@ void renderLogMessage(
|
||||
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||
|
||||
for (const auto& sector : sectors)
|
||||
r.add(fmt::format(" {}.{}.{}{}",
|
||||
r.add(fmt::format("{}.{}.{}{}",
|
||||
sector->logicalTrack,
|
||||
sector->logicalSide,
|
||||
sector->logicalSector,
|
||||
@@ -349,13 +349,14 @@ ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
||||
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
||||
offset += Layout::getHeadWidth())
|
||||
{
|
||||
log(BeginReadOperationLogMessage{
|
||||
trackInfo->physicalTrack + offset, trackInfo->physicalSide});
|
||||
|
||||
auto& fluxSourceIterator = fluxSourceIteratorHolder.getIterator(
|
||||
trackInfo->physicalTrack + offset, trackInfo->physicalSide);
|
||||
if (!fluxSourceIterator.hasNext())
|
||||
continue;
|
||||
|
||||
log(BeginReadOperationLogMessage{
|
||||
trackInfo->physicalTrack + offset, trackInfo->physicalSide});
|
||||
std::shared_ptr<const Fluxmap> fluxmap = fluxSourceIterator.next();
|
||||
// ->rescale(
|
||||
// 1.0 / globalConfig()->flux_source().rescale());
|
||||
|
||||
@@ -43,6 +43,7 @@ cxxprogram(
|
||||
"dep/stb",
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/vfs",
|
||||
"lib/config",
|
||||
"lib/fluxsource+proto_lib",
|
||||
|
||||
@@ -65,6 +65,7 @@ cxxprogram(
|
||||
"extras+icons",
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/vfs",
|
||||
"lib/config",
|
||||
"lib/fluxsource+proto_lib",
|
||||
|
||||
@@ -195,6 +195,7 @@ public:
|
||||
if (formatSelection == wxNOT_FOUND)
|
||||
error("no format selected");
|
||||
|
||||
ClearLog();
|
||||
globalConfig().clear();
|
||||
auto formatName = _formatNames[formatChoice->GetSelection()];
|
||||
globalConfig().readBaseConfigFile(formatName);
|
||||
@@ -292,7 +293,6 @@ public:
|
||||
globalConfig().set("usb.serial", serial);
|
||||
|
||||
globalConfig().validateAndThrow();
|
||||
ClearLog();
|
||||
}
|
||||
|
||||
const wxBitmap GetBitmap() override
|
||||
|
||||
@@ -24,13 +24,45 @@
|
||||
#include <wx/aboutdlg.h>
|
||||
#include <deque>
|
||||
|
||||
class CallbackOstream : public std::streambuf
|
||||
{
|
||||
public:
|
||||
CallbackOstream(std::function<void(const std::string&)> cb): _cb(cb) {}
|
||||
|
||||
public:
|
||||
std::streamsize xsputn(const char* p, std::streamsize n) override
|
||||
{
|
||||
_cb(std::string(p, n));
|
||||
return n;
|
||||
}
|
||||
|
||||
int_type overflow(int_type v) override
|
||||
{
|
||||
char c = v;
|
||||
_cb(std::string(&c, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(const std::string&)> _cb;
|
||||
};
|
||||
|
||||
class MainWindowImpl : public MainWindowGen, public MainWindow
|
||||
{
|
||||
private:
|
||||
class FilesystemOperation;
|
||||
|
||||
public:
|
||||
MainWindowImpl(): MainWindowGen(nullptr)
|
||||
MainWindowImpl():
|
||||
MainWindowGen(nullptr),
|
||||
_logStreamBuf(
|
||||
[this](const std::string& s)
|
||||
{
|
||||
if (_logWindow)
|
||||
_logWindow->GetTextControl()->AppendText(s);
|
||||
}),
|
||||
_logStream(&_logStreamBuf),
|
||||
_logRenderer(LogRenderer::create(_logStream))
|
||||
{
|
||||
Logger::setLogger(
|
||||
[&](const AnyLogMessage& message)
|
||||
@@ -203,7 +235,8 @@ public:
|
||||
|
||||
void OnLogMessage(const AnyLogMessage& message)
|
||||
{
|
||||
_logWindow->GetTextControl()->AppendText(Logger::toString(message));
|
||||
_logRenderer->add(message);
|
||||
_logStream.flush();
|
||||
|
||||
std::visit(
|
||||
overloaded{
|
||||
@@ -376,8 +409,11 @@ private:
|
||||
CustomStatusBar* _statusBar;
|
||||
wxTimer _exitTimer;
|
||||
std::unique_ptr<TextViewerWindow> _logWindow;
|
||||
CallbackOstream _logStreamBuf;
|
||||
std::ostream _logStream;
|
||||
std::unique_ptr<TextViewerWindow> _configWindow;
|
||||
std::unique_ptr<Context> _context;
|
||||
std::unique_ptr<LogRenderer> _logRenderer;
|
||||
};
|
||||
|
||||
wxWindow* FluxEngineApp::CreateMainWindow()
|
||||
|
||||
@@ -29,6 +29,18 @@ wxTextCtrl* TextViewerWindow::GetTextControl() const
|
||||
return textControl;
|
||||
}
|
||||
|
||||
std::streamsize TextViewerWindow::xsputn(const char* s, std::streamsize n)
|
||||
{
|
||||
textControl->AppendText(std::string(s, n));
|
||||
return n;
|
||||
}
|
||||
|
||||
int TextViewerWindow::overflow(int c)
|
||||
{
|
||||
char b = c;
|
||||
return xsputn(&b, 1);
|
||||
}
|
||||
|
||||
void TextViewerWindow::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
if (_autodestroy)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "layout.h"
|
||||
|
||||
class TextViewerWindow : public TextViewerWindowGen
|
||||
class TextViewerWindow : public TextViewerWindowGen, public std::streambuf
|
||||
{
|
||||
public:
|
||||
TextViewerWindow(wxWindow* parent,
|
||||
@@ -19,6 +19,10 @@ public:
|
||||
public:
|
||||
wxTextCtrl* GetTextControl() const;
|
||||
|
||||
public:
|
||||
std::streamsize xsputn(const char* s, std::streamsize n) override;
|
||||
int overflow(int c) override;
|
||||
|
||||
private:
|
||||
void OnClose(wxCloseEvent& event) override;
|
||||
|
||||
|
||||
@@ -55,8 +55,6 @@ export(
|
||||
"+fl2_proto_lib",
|
||||
"+fmt_lib",
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"+protobuf_lib",
|
||||
"+protocol",
|
||||
"+z_lib",
|
||||
@@ -69,6 +67,9 @@ export(
|
||||
"dep/snowhouse",
|
||||
"dep/stb",
|
||||
"lib/config",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"src/formats",
|
||||
],
|
||||
),
|
||||
@@ -84,11 +85,10 @@ export(
|
||||
"+fl2_proto_lib",
|
||||
"+fmt_lib",
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"+protobuf_lib",
|
||||
"+protocol",
|
||||
"+z_lib",
|
||||
"arch+proto_lib",
|
||||
"dep/adflib",
|
||||
"dep/agg",
|
||||
"dep/fatfs",
|
||||
@@ -96,8 +96,10 @@ export(
|
||||
"dep/libusbp",
|
||||
"dep/snowhouse",
|
||||
"dep/stb",
|
||||
"arch+proto_lib",
|
||||
"lib/config",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"src/formats",
|
||||
]
|
||||
+ ([".+test_proto_lib"] if n == "options" else [])
|
||||
|
||||
@@ -11,6 +11,7 @@ cxxprogram(
|
||||
deps=[
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/config+proto_lib",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"+fmt_lib",
|
||||
@@ -25,6 +26,7 @@ cxxprogram(
|
||||
deps=[
|
||||
"+lib",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/config+proto_lib",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"+fmt_lib",
|
||||
@@ -49,5 +51,6 @@ cxxprogram(
|
||||
"lib/fluxsource+proto_lib",
|
||||
"src/formats",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user