Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Log/LogManager.h
3186 views
1
// Copyright (C) 2003 Dolphin Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official SVN repository and contact information can be found at
16
// http://code.google.com/p/dolphin-emu/
17
18
#pragma once
19
20
#include "ppsspp_config.h"
21
22
#include <mutex>
23
#include <vector>
24
#include <cstdio>
25
26
#include "Common/Common.h"
27
#include "Common/CommonFuncs.h"
28
#include "Common/Log.h"
29
#include "Common/File/Path.h"
30
31
#define MAX_MESSAGES 8000
32
33
extern const char *hleCurrentThreadName;
34
35
// Struct that listeners can output how they want. For example, on Android we don't want to add
36
// timestamp or write the level as a string, those already exist.
37
struct LogMessage {
38
char timestamp[16];
39
char header[64]; // Filename/thread/etc. in front.
40
LogLevel level;
41
const char *log;
42
std::string msg; // The actual log message.
43
};
44
45
enum class LogOutput {
46
Stdio = (1 << 0),
47
DebugString = (1 << 1),
48
RingBuffer = (1 << 2),
49
File = (1 << 3),
50
WinConsole = (1 << 4),
51
Printf = (1 << 5),
52
ExternalCallback = (1 << 6),
53
};
54
ENUM_CLASS_BITOPS(LogOutput);
55
56
class RingbufferLog {
57
public:
58
void Log(const LogMessage &msg);
59
int GetCount() const { return count_ < MAX_LOGS ? count_ : MAX_LOGS; }
60
std::string_view TextAt(int i) const { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)].msg; }
61
LogLevel LevelAt(int i) const { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)].level; }
62
63
void Clear() {
64
curMessage_ = 0;
65
count_ = 0;
66
}
67
68
private:
69
enum { MAX_LOGS = 256 };
70
LogMessage messages_[MAX_LOGS];
71
int curMessage_ = 0;
72
int count_ = 0;
73
};
74
75
class Section;
76
class ConsoleListener;
77
78
typedef void (*LogCallback)(const LogMessage &message, void *userdata);
79
extern bool *g_bLogEnabledSetting;
80
81
class LogManager {
82
public:
83
LogManager();
84
~LogManager();
85
86
void SetOutputsEnabled(LogOutput outputs);
87
LogOutput GetOutputsEnabled() const {
88
return outputs_;
89
}
90
void EnableOutput(LogOutput output) {
91
SetOutputsEnabled(outputs_ | output);
92
}
93
void DisableOutput(LogOutput output) {
94
LogOutput temp = outputs_;
95
temp &= ~output;
96
SetOutputsEnabled(temp);
97
}
98
void EnableOutput(LogOutput output, bool enabled) {
99
if (enabled) {
100
EnableOutput(output);
101
} else {
102
DisableOutput(output);
103
}
104
}
105
106
static u32 GetMaxLevel() { return (u32)MAX_LOGLEVEL; }
107
static int GetNumChannels() { return (int)Log::NUMBER_OF_LOGS; }
108
109
void LogLine(LogLevel level, Log type,
110
const char *file, int line, const char *fmt, va_list args);
111
112
LogChannel *GetLogChannel(Log type) {
113
return &g_log[(size_t)type];
114
}
115
116
void SetLogLevel(Log type, LogLevel level) {
117
g_log[(size_t)type].level = level;
118
}
119
120
void SetAllLogLevels(LogLevel level) {
121
for (int i = 0; i < (int)Log::NUMBER_OF_LOGS; ++i) {
122
g_log[i].level = level;
123
}
124
}
125
126
void SetEnabled(Log type, bool enable) {
127
g_log[(size_t)type].enabled = enable;
128
}
129
130
LogLevel GetLogLevel(Log type) {
131
return g_log[(size_t)type].level;
132
}
133
134
#if PPSSPP_PLATFORM(WINDOWS)
135
ConsoleListener *GetConsoleListener() const {
136
return consoleLog_;
137
}
138
#endif
139
140
const RingbufferLog *GetRingbuffer() const {
141
return &ringLog_;
142
}
143
144
void Init(bool *enabledSetting, bool headless = false);
145
void Shutdown();
146
147
void SetExternalLogCallback(LogCallback callback, void *userdata) {
148
externalCallback_ = callback;
149
externalUserData_ = userdata;
150
}
151
152
void SetFileLogPath(const Path &filename);
153
const Path &GetLogFilePath() const { return logFilename_; }
154
155
void SaveConfig(Section *section);
156
void LoadConfig(const Section *section);
157
158
static const char *GetLogTypeName(Log type);
159
160
private:
161
// Prevent copies.
162
LogManager(const LogManager &) = delete;
163
void operator=(const LogManager &) = delete;
164
165
bool initialized_ = false;
166
167
#if PPSSPP_PLATFORM(WINDOWS)
168
ConsoleListener *consoleLog_ = nullptr;
169
#endif
170
// Stdio logging
171
void StdioLog(const LogMessage &message);
172
std::mutex stdioLock_;
173
bool stdioUseColor_ = true;
174
175
LogOutput outputs_ = (LogOutput)0;
176
177
// File logging
178
std::mutex logFileLock_;
179
FILE *fp_ = nullptr;
180
bool logFileOpenFailed_ = false;
181
Path logFilename_;
182
183
// Ring buffer
184
RingbufferLog ringLog_;
185
186
// Callback
187
LogCallback externalCallback_ = nullptr;
188
void *externalUserData_ = nullptr;
189
};
190
191
extern LogManager g_logManager;
192
193