From 6045a3e9193fcde36fa978b81cffe428fa8c90fc Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Sun, 14 Apr 2024 19:43:55 +0200 Subject: [PATCH] misc: add log levels and add SetPUPTriggerCallback (#41) --- include/DMDUtil/Config.h | 27 +++++++++++++++++++- include/DMDUtil/DMD.h | 2 +- src/Config.cpp | 4 +++ src/DMD.cpp | 31 +++++++++++++++-------- src/Logger.cpp | 10 +++++--- src/Logger.h | 4 ++- src/PixelcadeDMD.cpp | 28 ++++++++++----------- src/Serum.cpp | 4 +-- src/dmdServer.cpp | 54 +++++++++++++++++++++------------------- src/test.h | 2 +- 10 files changed, 105 insertions(+), 61 deletions(-) diff --git a/include/DMDUtil/Config.h b/include/DMDUtil/Config.h index 12c6e5f..28d31db 100644 --- a/include/DMDUtil/Config.h +++ b/include/DMDUtil/Config.h @@ -11,7 +11,22 @@ #include #include -typedef void(DMDUTILCALLBACK* DMDUtil_LogCallback)(const char* format, va_list args); +typedef enum +{ + DMDUtil_LogLevel_INFO, + DMDUtil_LogLevel_ERROR, + DMDUtil_LogLevel_DEBUG +} DMDUtil_LogLevel; + +typedef void(DMDUTILCALLBACK* DMDUtil_LogCallback)(DMDUtil_LogLevel logLevel, const char* format, va_list args); + +typedef void(DMDUTILCALLBACK* DMDUtil_PUPTriggerCallback)(uint16_t id, void* userData); + +struct DMDUtil_PUPTriggerCallbackContext +{ + DMDUtil_PUPTriggerCallback callback; + void* pUserData; +}; namespace DMDUtil { @@ -58,8 +73,16 @@ class DMDUTILAPI Config const char* GetDMDServerAddr() const { return m_dmdServerAddr.c_str(); } void SetDMDServerPort(int port) { m_dmdServerPort = port; } int GetDMDServerPort() const { return m_dmdServerPort; } + DMDUtil_LogLevel GetLogLevel() const { return m_logLevel; } + void SetLogLevel(DMDUtil_LogLevel logLevel) { m_logLevel = logLevel; } DMDUtil_LogCallback GetLogCallback() const { return m_logCallback; } void SetLogCallback(DMDUtil_LogCallback callback) { m_logCallback = callback; } + DMDUtil_PUPTriggerCallbackContext GetPUPTriggerCallbackContext() const { return m_pupTriggerCallbackContext; } + void SetPUPTriggerCallback(DMDUtil_PUPTriggerCallback callback, void* pUserData) + { + m_pupTriggerCallbackContext.callback = callback; + m_pupTriggerCallbackContext.pUserData = pUserData; + } private: Config(); @@ -85,7 +108,9 @@ class DMDUTILAPI Config bool m_pixelcade; std::string m_pixelcadeDevice; int m_pixelcadeMatrix; + DMDUtil_LogLevel m_logLevel; DMDUtil_LogCallback m_logCallback; + DMDUtil_PUPTriggerCallbackContext m_pupTriggerCallbackContext; }; } // namespace DMDUtil diff --git a/include/DMDUtil/DMD.h b/include/DMDUtil/DMD.h index a5cd255..f9f7fdd 100644 --- a/include/DMDUtil/DMD.h +++ b/include/DMDUtil/DMD.h @@ -155,7 +155,7 @@ class DMDUTILAPI DMD void UpdateData(const uint8_t* pData, int depth, uint16_t width, uint16_t height, uint8_t r, uint8_t g, uint8_t b, Mode mode, bool buffered = false); void AdjustRGB24Depth(uint8_t* pData, uint8_t* pDstData, int length, uint8_t* palette, uint8_t depth); - void handleTrigger(uint16_t id); + void HandleTrigger(uint16_t id); void DmdFrameThread(); void LevelDMDThread(); diff --git a/src/Config.cpp b/src/Config.cpp index 6fe9c3e..7b77b1f 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -1,5 +1,7 @@ #include "DMDUtil/Config.h" +#include + namespace DMDUtil { @@ -33,7 +35,9 @@ Config::Config() m_dmdServer = false; m_dmdServerAddr = "localhost"; m_dmdServerPort = 6789; + m_logLevel = DMDUtil_LogLevel_INFO; m_logCallback = nullptr; + memset(&m_pupTriggerCallbackContext, 0, sizeof(m_pupTriggerCallbackContext)); } } // namespace DMDUtil diff --git a/src/DMD.cpp b/src/DMD.cpp index d9f0e4a..fe2fa35 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -30,7 +30,7 @@ void PUPDMDCALLBACK PUPDMDLogCallback(const char* format, va_list args, const vo char buffer[1024]; vsnprintf(buffer, sizeof(buffer), format, args); - Log("%s", buffer); + Log(DMDUtil_LogLevel_INFO, "%s", buffer); } void ZEDMDCALLBACK ZeDMDLogCallback(const char* format, va_list args, const void* pUserData) @@ -38,7 +38,7 @@ void ZEDMDCALLBACK ZeDMDLogCallback(const char* format, va_list args, const void char buffer[1024]; vsnprintf(buffer, sizeof(buffer), format, args); - Log("%s", buffer); + Log(DMDUtil_LogLevel_INFO, "%s", buffer); } bool DMD::m_finding = false; @@ -169,12 +169,14 @@ bool DMD::ConnectDMDServer() { Config* const pConfig = Config::GetInstance(); sockpp::initialize(); - Log("Connecting DMDServer on %s:%d", pConfig->GetDMDServerAddr(), pConfig->GetDMDServerPort()); + Log(DMDUtil_LogLevel_INFO, "Connecting DMDServer on %s:%d", pConfig->GetDMDServerAddr(), + pConfig->GetDMDServerPort()); m_pDMDServerConnector = new sockpp::tcp_connector({pConfig->GetDMDServerAddr(), (in_port_t)pConfig->GetDMDServerPort()}); if (!m_pDMDServerConnector) { - Log("DMDServer connection to %s:%d failed!", pConfig->GetDMDServerAddr(), pConfig->GetDMDServerPort()); + Log(DMDUtil_LogLevel_INFO, "DMDServer connection to %s:%d failed!", pConfig->GetDMDServerAddr(), + pConfig->GetDMDServerPort()); } } return (m_pDMDServerConnector); @@ -668,7 +670,7 @@ void DMD::ZeDMDThread() } m_serumMutex.unlock(); - if (triggerID > 0) handleTrigger(triggerID); + if (triggerID > 0) HandleTrigger(triggerID); } else { @@ -831,7 +833,7 @@ void DMD::PixelcadeDMDThread() m_pUpdateBufferQueue[bufferPosition]->height, &triggerID); m_serumMutex.unlock(); - if (triggerID > 0) handleTrigger(triggerID); + if (triggerID > 0) HandleTrigger(triggerID); } else { @@ -1006,7 +1008,7 @@ void DMD::RGB24DMDThread() m_pUpdateBufferQueue[bufferPosition]->height, &triggerID); m_serumMutex.unlock(); - if (triggerID > 0) handleTrigger(triggerID); + if (triggerID > 0) HandleTrigger(triggerID); } else { @@ -1425,17 +1427,24 @@ void DMD::PupDMDThread() free(pFrame); } - if (triggerID > 0) handleTrigger(triggerID); + if (triggerID > 0) HandleTrigger(triggerID); } } } } } -void DMD::handleTrigger(uint16_t id) +void DMD::HandleTrigger(uint16_t id) { - Log("PUP Trigger D%d", id); - // @todo + static Config* pConfig = Config::GetInstance(); + + Log(DMDUtil_LogLevel_DEBUG, "HandleTrigger: id=D%d", id); + + DMDUtil_PUPTriggerCallbackContext callbackContext = pConfig->GetPUPTriggerCallbackContext(); + if (callbackContext.callback != nullptr) + { + (*callbackContext.callback)(id, callbackContext.pUserData); + } } } // namespace DMDUtil diff --git a/src/Logger.cpp b/src/Logger.cpp index c4cea93..b679d2b 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -5,15 +5,17 @@ namespace DMDUtil { -void Log(const char *format, ...) +void Log(DMDUtil_LogLevel logLevel, const char* format, ...) { - DMDUtil_LogCallback logCallback = Config::GetInstance()->GetLogCallback(); + static Config* pConfig = pConfig->GetInstance(); - if (!logCallback) return; + DMDUtil_LogCallback logCallback = pConfig->GetLogCallback(); + + if (!logCallback || logLevel < pConfig->GetLogLevel()) return; va_list args; va_start(args, format); - (*(logCallback))(format, args); + (*(logCallback))(logLevel, format, args); va_end(args); } diff --git a/src/Logger.h b/src/Logger.h index 9243d1c..e099870 100644 --- a/src/Logger.h +++ b/src/Logger.h @@ -1,8 +1,10 @@ #pragma once +#include "DMDUtil/Config.h" + namespace DMDUtil { -void Log(const char *format, ...); +void Log(DMDUtil_LogLevel logLevel, const char* format, ...); } diff --git a/src/PixelcadeDMD.cpp b/src/PixelcadeDMD.cpp index f4258b1..fe32a3b 100644 --- a/src/PixelcadeDMD.cpp +++ b/src/PixelcadeDMD.cpp @@ -53,15 +53,15 @@ PixelcadeDMD* PixelcadeDMD::Connect(const char* pDevice, int matrix, int width, if (pDevice && *pDevice != 0) { - Log("Connecting to Pixelcade on %s...", pDevice); + Log(DMDUtil_LogLevel_INFO, "Connecting to Pixelcade on %s...", pDevice); pPixelcadeDMD = Open(pDevice, matrix, width, height); - if (!pPixelcadeDMD) Log("Unable to connect to Pixelcade on %s", pDevice); + if (!pPixelcadeDMD) Log(DMDUtil_LogLevel_INFO, "Unable to connect to Pixelcade on %s", pDevice); } else { - Log("Searching for Pixelcade..."); + Log(DMDUtil_LogLevel_INFO, "Searching for Pixelcade..."); struct sp_port** ppPorts; enum sp_return result = sp_list_ports(&ppPorts); @@ -75,7 +75,7 @@ PixelcadeDMD* PixelcadeDMD::Connect(const char* pDevice, int matrix, int width, sp_free_port_list(ppPorts); } - if (!pPixelcadeDMD) Log("Unable to find Pixelcade"); + if (!pPixelcadeDMD) Log(DMDUtil_LogLevel_INFO, "Unable to find Pixelcade"); } return pPixelcadeDMD; @@ -116,7 +116,7 @@ PixelcadeDMD* PixelcadeDMD::Open(const char* pDevice, int matrix, int width, int { sp_close(pSerialPort); sp_free_port(pSerialPort); - // Log("Pixelcade expected new connection to return 0x0, but got 0x%02d", response[0]); + // Log(DMDUtil_LogLevel_INFO, "Pixelcade expected new connection to return 0x0, but got 0x%02d", response[0]); return nullptr; } @@ -124,8 +124,8 @@ PixelcadeDMD* PixelcadeDMD::Open(const char* pDevice, int matrix, int width, int { sp_close(pSerialPort); sp_free_port(pSerialPort); - // Log("Pixelcade expected magic code to equal IOIO but got %c%c%c%c", response[1], response[2], response[3], - // response[4]); + // Log(DMDUtil_LogLevel_INFO, "Pixelcade expected magic code to equal IOIO but got %c%c%c%c", response[1], + // response[2], response[3], response[4]); return nullptr; } @@ -138,8 +138,8 @@ PixelcadeDMD* PixelcadeDMD::Open(const char* pDevice, int matrix, int width, int char firmware[9] = {0}; memcpy(firmware, response + 21, 8); - Log("Pixelcade found: device=%s, Hardware ID=%s, Bootloader ID=%s, Firmware=%s", pDevice, hardwareId, bootloaderId, - firmware); + Log(DMDUtil_LogLevel_INFO, "Pixelcade found: device=%s, Hardware ID=%s, Bootloader ID=%s, Firmware=%s", pDevice, + hardwareId, bootloaderId, firmware); return new PixelcadeDMD(pSerialPort, matrix, width, height); } @@ -171,7 +171,7 @@ void PixelcadeDMD::Run() m_pThread = new std::thread( [this]() { - Log("PixelcadeDMD run thread starting"); + Log(DMDUtil_LogLevel_INFO, "PixelcadeDMD run thread starting"); EnableRgbLedMatrix(4, 16); int errors = 0; @@ -212,7 +212,7 @@ void PixelcadeDMD::Run() { if (errors > 0) { - Log("Communication to Pixelcade restored after %d frames", errors); + Log(DMDUtil_LogLevel_INFO, "Communication to Pixelcade restored after %d frames", errors); errors = 0; } } @@ -220,7 +220,7 @@ void PixelcadeDMD::Run() { if (errors++ > PIXELCADE_MAX_NO_RESPONSE) { - Log("Error while transmitting to Pixelcade: no response for the past %d frames", + Log(DMDUtil_LogLevel_INFO, "Error while transmitting to Pixelcade: no response for the past %d frames", PIXELCADE_MAX_NO_RESPONSE); m_running = false; } @@ -228,7 +228,7 @@ void PixelcadeDMD::Run() else if (response == SP_ERR_FAIL) { char* pMessage = sp_last_error_message(); - Log("Error while transmitting to Pixelcade: %s", pMessage); + Log(DMDUtil_LogLevel_INFO, "Error while transmitting to Pixelcade: %s", pMessage); sp_free_error_message(pMessage); m_running = false; } @@ -251,7 +251,7 @@ void PixelcadeDMD::Run() m_pSerialPort = nullptr; - Log("PixelcadeDMD run thread finished"); + Log(DMDUtil_LogLevel_INFO, "PixelcadeDMD run thread finished"); }); } diff --git a/src/Serum.cpp b/src/Serum.cpp index 8577ccf..afbc524 100644 --- a/src/Serum.cpp +++ b/src/Serum.cpp @@ -39,8 +39,8 @@ Serum* Serum::Load(const char* const altColorPath, const char* const romName) return nullptr; } - Log("Serum loaded: romName=%s, width=%d, height=%d, numColors=%d, numTriggers=%d", romName, width, height, numColors, - numTriggers); + Log(DMDUtil_LogLevel_INFO, "Serum loaded: romName=%s, width=%d, height=%d, numColors=%d, numTriggers=%d", romName, + width, height, numColors, numTriggers); m_isLoaded = true; diff --git a/src/dmdServer.cpp b/src/dmdServer.cpp index c52c7a4..385c87a 100644 --- a/src/dmdServer.cpp +++ b/src/dmdServer.cpp @@ -70,7 +70,7 @@ static struct cag_option options[] = { .description = "Enables verbose logging, includes normal logging (optional, default is no logging)"}, {.identifier = 'h', .access_letters = "h", .access_name = "help", .description = "Show help"}}; -void DMDUTILCALLBACK LogCallback(const char* format, va_list args) +void DMDUTILCALLBACK LogCallback(DMDUtil_LogLevel logLevel, const char* format, va_list args) { char buffer[1024]; vsnprintf(buffer, sizeof(buffer), format, args); @@ -85,7 +85,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) // Disconnect others is only allowed once per client. bool handleDisconnectOthers = true; - if (opt_verbose) DMDUtil::Log("%d: New DMD client %d connected", threadId, threadId); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: New DMD client %d connected", threadId, threadId); while (threadId == currentThreadId || disconnectOtherClients == 0 || disconnectOtherClients <= threadId) { @@ -102,10 +102,10 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) { if (opt_verbose) { - DMDUtil::Log("%d: Received DMDStream header version %d for DMD mode %d", threadId, pStreamHeader->version, - pStreamHeader->mode); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Received DMDStream header version %d for DMD mode %d", threadId, + pStreamHeader->version, pStreamHeader->mode); if (pStreamHeader->buffered && threadId == currentThreadId) - DMDUtil::Log("%d: Next data will be buffered", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Next data will be buffered", threadId); } // Only the current (most recent) thread is allowed to disconnect other clients. @@ -115,7 +115,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) disconnectOtherClients = threadId; threadMutex.unlock(); handleDisconnectOthers = false; - if (opt_verbose) DMDUtil::Log("%d: Other clients will be disconnected", threadId); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Other clients will be disconnected", threadId); } switch (pStreamHeader->mode) @@ -131,7 +131,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) threadId == currentThreadId) { if (opt_verbose) - DMDUtil::Log("%d: Received paths header: ROM '%s', AltColorPath '%s', PupPath '%s'", threadId, + DMDUtil::Log(DMDUtil_LogLevel_INFO, + "%d: Received paths header: ROM '%s', AltColorPath '%s', PupPath '%s'", threadId, pathsHeader.name, pathsHeader.altColorPath, pathsHeader.pupVideosPath); DMDUtil::DMD::Update data; memcpy(&data, buffer, n); @@ -146,16 +147,16 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } else { - DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: TCP data package is missing or corrupted!", threadId); } } else if (threadId != currentThreadId) { - DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Client %d blocks the DMD", threadId, currentThreadId); } else { - DMDUtil::Log("%d: Paths header is missing!", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Paths header is missing!", threadId); } } break; @@ -173,11 +174,11 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } else if (threadId != currentThreadId) { - DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Client %d blocks the DMD", threadId, currentThreadId); } else { - DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: TCP data package is missing or corrupted!", threadId); } break; @@ -190,11 +191,11 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } else if (threadId != currentThreadId) { - DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Client %d blocks the DMD", threadId, currentThreadId); } else { - DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: TCP data package is missing or corrupted!", threadId); } break; @@ -205,18 +206,18 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) } else if (threadId == currentThreadId) { - DMDUtil::Log("%d: Received unknown TCP package", threadId); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Received unknown TCP package", threadId); } } } if (opt_verbose && disconnectOtherClients != 0 && disconnectOtherClients > threadId) - DMDUtil::Log("%d: Client %d requested disconnect", threadId, disconnectOtherClients); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Client %d requested disconnect", threadId, disconnectOtherClients); // Display a buffered frame or clear the display on disconnect of the current thread. if (threadId == currentThreadId && !pStreamHeader->buffered && !pDmd->QueueBuffer()) { - if (opt_verbose) DMDUtil::Log("%d: Clear screen on disconnect", threadId); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: Clear screen on disconnect", threadId); // Clear the DMD by sending a black screen. // Fixed dimension of 128x32 should be OK for all devices. memset(buffer, 0, sizeof(DMDUtil::DMD::Update)); @@ -246,11 +247,11 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) currentThreadId = (threads.size() >= 1) ? threads.back() : 0; } - if (opt_verbose) DMDUtil::Log("%d: DMD client %d set as current", threadId, currentThreadId); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: DMD client %d set as current", threadId, currentThreadId); } threadMutex.unlock(); - if (opt_verbose) DMDUtil::Log("%d: DMD client %d disconnected", threadId, threadId); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: DMD client %d disconnected", threadId, threadId); free(pStreamHeader); } @@ -290,7 +291,7 @@ int main(int argc, char* argv[]) pConfig->SetPixelcadeDevice(r.Get("Pixelcade", "Device", "").c_str()); pConfig->SetPixelcadeMatrix(r.Get("Pixelcade", "Matrix", -1)); - if (opt_verbose) DMDUtil::Log("Loaded config file"); + if (opt_verbose) DMDUtil::Log(DMDUtil_LogLevel_INFO, "Loaded config file"); } else if (identifier == 'o') { @@ -334,12 +335,12 @@ int main(int argc, char* argv[]) sockpp::initialize(); if (opt_verbose) - DMDUtil::Log("Opening DMDServer, listining for TCP connections on %s:%d", pConfig->GetDMDServerAddr(), - pConfig->GetDMDServerPort()); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "Opening DMDServer, listining for TCP connections on %s:%d", + pConfig->GetDMDServerAddr(), pConfig->GetDMDServerPort()); sockpp::tcp_acceptor acc({pConfig->GetDMDServerAddr(), (in_port_t)pConfig->GetDMDServerPort()}); if (!acc) { - DMDUtil::Log("Error creating the DMDServer acceptor: %s", acc.last_error_str().c_str()); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "Error creating the DMDServer acceptor: %s", acc.last_error_str().c_str()); return 1; } @@ -371,7 +372,7 @@ int main(int argc, char* argv[]) if (!sock) { - DMDUtil::Log("Error accepting incoming connection: %s", acc.last_error_str().c_str()); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "Error accepting incoming connection: %s", acc.last_error_str().c_str()); } else { @@ -379,13 +380,14 @@ int main(int argc, char* argv[]) currentThreadId = ++threadId; threads.push_back(currentThreadId); threadMutex.unlock(); - if (opt_verbose) DMDUtil::Log("%d: DMD client %d set as current", threadId, currentThreadId); + if (opt_verbose) + DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: DMD client %d set as current", threadId, currentThreadId); // Create a thread and transfer the new stream to it. thread thr(run, std::move(sock), currentThreadId); thr.detach(); } } - DMDUtil::Log("No DMD displays found."); + DMDUtil::Log(DMDUtil_LogLevel_INFO, "No DMD displays found."); return 2; } diff --git a/src/test.h b/src/test.h index 077676b..364270e 100644 --- a/src/test.h +++ b/src/test.h @@ -4,7 +4,7 @@ #include "DMDUtil/DMDUtil.h" -void DMDUTILCALLBACK LogCallback(const char* format, va_list args) +void DMDUTILCALLBACK LogCallback(DMDUtil_LogLevel logLevel, const char* format, va_list args) { char buffer[1024]; vsnprintf(buffer, sizeof(buffer), format, args);