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);
68 log_print_ptr->println(print_buffer);
69 log_print_ptr->flush();
74 char* str() {
return print_buffer; }
77 static AudioLogger& instance() {
78 static AudioLogger* ptr;
80 ptr =
new AudioLogger;
85 LogLevel level() {
return log_level; }
87 void print(
const char* c) { log_print_ptr->print(c); }
89 void printChar(
char c) { log_print_ptr->print(c); }
91 void printCharHex(
char c) {
93 unsigned char val = c;
94 snprintf(tmp, 5,
"%02X ", val);
95 log_print_ptr->print(tmp);
99 Print* log_print_ptr = &LOG_STREAM;
100 LogLevel log_level = LOG_LEVEL;
101 char print_buffer[LOG_PRINTF_BUFFER_SIZE];
105 const char* levelName(LogLevel level)
const {
119 int printPrefix(
const char* file,
int line, LogLevel current_level)
const {
120 const char* file_name = strrchr(file,
'/') ? strrchr(file,
'/') + 1 : file;
121 const char* level_code = levelName(current_level);
122 int len = log_print_ptr->print(
"[");
123 len += log_print_ptr->print(level_code);
124 len += log_print_ptr->print(
"] ");
125 len += log_print_ptr->print(file_name);
126 len += log_print_ptr->print(
" : ");
127 len += log_print_ptr->print(line);
128 len += log_print_ptr->print(
" - ");
133static AudioLogger& AudioToolsLogger = AudioLogger::instance();
134using AudioToolsLogLevel = AudioLogger::LogLevel;
137class CustomLogLevel {
139 AudioLogger::LogLevel getActual() {
return actual; }
142 void set(AudioLogger::LogLevel level) {
144 original = AudioLogger::instance().level();
151 AudioLogger::instance().begin(Serial, actual);
157 AudioLogger::instance().begin(Serial, original);
163 AudioLogger::LogLevel original;
164 AudioLogger::LogLevel actual;
174#define LOG_OUT_PGMEM(level, fmt, ...) \
176 LockGuard guard{audio_logger_mutex}; \
177 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
178 snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, PSTR(fmt), \
180 AudioLogger::instance().println(); \
183#define LOG_OUT(level, fmt, ...) \
185 LockGuard guard{audio_logger_mutex}; \
186 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
187 snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, fmt, \
189 AudioLogger::instance().println(); \
191#define LOG_MIN(level) \
193 LockGuard guard{audio_logger_mutex}; \
194 AudioLogger::instance().prefix(__FILE__, __LINE__, level); \
195 AudioLogger::instance().println(); \
199#define LOGD(fmt, ...) \
200 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
201 LOG_MIN(AudioLogger::Debug); \
203#define LOGI(fmt, ...) \
204 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
205 LOG_MIN(AudioLogger::Info); \
207#define LOGW(fmt, ...) \
208 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
209 LOG_MIN(AudioLogger::Warning); \
211#define LOGE(fmt, ...) \
212 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
213 LOG_MIN(AudioLogger::Error); \
217#define LOGD(fmt, ...) \
218 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
219 LOG_OUT_PGMEM(AudioLogger::Debug, fmt, ##__VA_ARGS__); \
221#define LOGI(fmt, ...) \
222 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
223 LOG_OUT_PGMEM(AudioLogger::Info, fmt, ##__VA_ARGS__); \
225#define LOGW(fmt, ...) \
226 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
227 LOG_OUT_PGMEM(AudioLogger::Warning, fmt, ##__VA_ARGS__); \
229#define LOGE(fmt, ...) \
230 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
231 LOG_OUT_PGMEM(AudioLogger::Error, fmt, ##__VA_ARGS__); \
236#if defined(NO_TRACED) || defined(NO_TRACE)
240 if (AudioLogger::instance().level() <= AudioLogger::Debug) { \
241 LOG_OUT(AudioLogger::Debug, LOG_METHOD); \
245#if defined(NO_TRACEI) || defined(NO_TRACE)
249 if (AudioLogger::instance().level() <= AudioLogger::Info) { \
250 LOG_OUT(AudioLogger::Info, LOG_METHOD); \
254#if defined(NO_TRACEW) || defined(NO_TRACE)
258 if (AudioLogger::instance().level() <= AudioLogger::Warning) { \
259 LOG_OUT(AudioLogger::Warning, LOG_METHOD); \
263#if defined(NO_TRACEE) || defined(NO_TRACE)
267 if (AudioLogger::instance().level() <= AudioLogger::Error) { \
268 LOG_OUT(AudioLogger::Error, LOG_METHOD); \