3#include "AudioToolsConfig.h"
4#if defined(ARDUINO) && !defined(IS_MIN_DESKTOP)
8#include "AudioTools/Concurrency/LockGuard.h"
10#include "AudioTools/Concurrency/RP2040/MutexRP2040.h"
12#include "AudioTools/Concurrency/RTOS/MutexRTOS.h"
21static MutexRTOS audio_logger_mutex;
23static MutexRP2040 audio_logger_mutex;
25static MutexBase audio_logger_mutex;
42 enum LogLevel { Debug, Info, Warning, Error };
45 void begin(Print& out, LogLevel level = LOG_LEVEL) {
46 this->log_print_ptr = &out;
47 this->log_level = level;
51 void setLogLevel(LogLevel level) { this->log_level = level; }
54 bool isLogging(LogLevel level = Info) {
55 return log_print_ptr !=
nullptr && level >= log_level;
58 AudioLogger& prefix(
const char* file,
int line, LogLevel current_level) {
59 printPrefix(file, line, current_level);
64#if defined(IS_DESKTOP) || defined(IS_DESKTOP_WITH_TIME_ONLY)
65 fprintf(stderr,
"%s\n", print_buffer);
67 log_print_ptr->println(print_buffer);
68 log_print_ptr->flush();
73 char* str() {
return print_buffer; }
76 static AudioLogger& instance() {
77 static AudioLogger* ptr;
79 ptr =
new AudioLogger;
84 LogLevel level() {
return log_level; }
86 void print(
const char* c) { log_print_ptr->print(c); }
88 void printChar(
char c) { log_print_ptr->print(c); }
90 void printCharHex(
char c) {
92 unsigned char val = c;
93 snprintf(tmp, 5,
"%02X ", val);
94 log_print_ptr->print(tmp);
98 Print* log_print_ptr = &LOG_STREAM;
99 LogLevel log_level = LOG_LEVEL;
100 char print_buffer[LOG_PRINTF_BUFFER_SIZE];
104 const char* levelName(LogLevel level)
const {
118 int printPrefix(
const char* file,
int line, LogLevel current_level)
const {
119 const char* file_name = strrchr(file,
'/') ? strrchr(file,
'/') + 1 : file;
120 const char* level_code = levelName(current_level);
121 int len = log_print_ptr->print(
"[");
122 len += log_print_ptr->print(level_code);
123 len += log_print_ptr->print(
"] ");
124 len += log_print_ptr->print(file_name);
125 len += log_print_ptr->print(
" : ");
126 len += log_print_ptr->print(line);
127 len += log_print_ptr->print(
" - ");
132static AudioLogger& AudioToolsLogger = AudioLogger::instance();
133using AudioToolsLogLevel = AudioLogger::LogLevel;
136class CustomLogLevel {
138 AudioLogger::LogLevel getActual() {
return actual; }
141 void set(AudioLogger::LogLevel level) {
143 original = AudioLogger::instance().level();
150 AudioLogger::instance().begin(Serial, actual);
156 AudioLogger::instance().begin(Serial, original);
162 AudioLogger::LogLevel original;
163 AudioLogger::LogLevel actual;
173#define LOG_OUT_PGMEM(level, fmt, ...) \
175 LockGuard guard{audio_logger_mutex}; \
176 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
177 snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, PSTR(fmt), \
179 AudioLogger::instance().println(); \
182#define LOG_OUT(level, fmt, ...) \
184 LockGuard guard{audio_logger_mutex}; \
185 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
186 snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, fmt, \
188 AudioLogger::instance().println(); \
190#define LOG_MIN(level) \
192 LockGuard guard{audio_logger_mutex}; \
193 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
194 AudioLogger::instance().println(); \
198#define LOGD(fmt, ...) \
199 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
200 LOG_MIN(AudioLogger::Debug); \
202#define LOGI(fmt, ...) \
203 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
204 LOG_MIN(AudioLogger::Info); \
206#define LOGW(fmt, ...) \
207 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
208 LOG_MIN(AudioLogger::Warning); \
210#define LOGE(fmt, ...) \
211 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
212 LOG_MIN(AudioLogger::Error); \
216#define LOGD(fmt, ...) \
217 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
218 LOG_OUT_PGMEM(AudioLogger::Debug, fmt, ##__VA_ARGS__); \
220#define LOGI(fmt, ...) \
221 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
222 LOG_OUT_PGMEM(AudioLogger::Info, fmt, ##__VA_ARGS__); \
224#define LOGW(fmt, ...) \
225 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
226 LOG_OUT_PGMEM(AudioLogger::Warning, fmt, ##__VA_ARGS__); \
228#define LOGE(fmt, ...) \
229 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
230 LOG_OUT_PGMEM(AudioLogger::Error, fmt, ##__VA_ARGS__); \
235#if defined(NO_TRACED) || defined(NO_TRACE)
239 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
240 LOG_OUT(AudioLogger::Debug, LOG_METHOD); \
244#if defined(NO_TRACEI) || defined(NO_TRACE)
248 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
249 LOG_OUT(AudioLogger::Info, LOG_METHOD); \
253#if defined(NO_TRACEW) || defined(NO_TRACE)
257 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
258 LOG_OUT(AudioLogger::Warning, LOG_METHOD); \
262#if defined(NO_TRACEE) || defined(NO_TRACE)
266 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
267 LOG_OUT(AudioLogger::Error, LOG_METHOD); \