7 changed files with 2 additions and 851 deletions
-
1src/citra_qt/main.cpp
-
4src/common/CMakeLists.txt
-
319src/common/console_listener.cpp
-
38src/common/console_listener.h
-
127src/common/log.h
-
198src/common/log_manager.cpp
-
166src/common/log_manager.h
@ -1,319 +0,0 @@ |
|||
// Copyright 2013 Dolphin Emulator Project
|
|||
// Licensed under GPLv2
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <algorithm>
|
|||
|
|||
#ifdef _WIN32
|
|||
#include <windows.h>
|
|||
#include <array>
|
|||
#endif
|
|||
|
|||
#include "common/common.h"
|
|||
#include "common/log_manager.h" // Common
|
|||
#include "common/console_listener.h" // Common
|
|||
|
|||
ConsoleListener::ConsoleListener() |
|||
{ |
|||
#ifdef _WIN32
|
|||
hConsole = nullptr; |
|||
bUseColor = true; |
|||
#else
|
|||
bUseColor = isatty(fileno(stdout)); |
|||
#endif
|
|||
} |
|||
|
|||
ConsoleListener::~ConsoleListener() |
|||
{ |
|||
Close(); |
|||
} |
|||
|
|||
// 100, 100, "Dolphin Log Console"
|
|||
// Open console window - width and height is the size of console window
|
|||
// Name is the window title
|
|||
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title) |
|||
{ |
|||
#ifdef _WIN32
|
|||
if (!GetConsoleWindow()) |
|||
{ |
|||
// Open the console window and create the window handle for GetStdHandle()
|
|||
AllocConsole(); |
|||
// Hide
|
|||
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE); |
|||
// Save the window handle that AllocConsole() created
|
|||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
// Set the console window title
|
|||
SetConsoleTitle(Common::UTF8ToTStr(Title).c_str()); |
|||
// Set letter space
|
|||
LetterSpace(80, 4000); |
|||
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
|
|||
} |
|||
else |
|||
{ |
|||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void ConsoleListener::UpdateHandle() |
|||
{ |
|||
#ifdef _WIN32
|
|||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
#endif
|
|||
} |
|||
|
|||
// Close the console window and close the eventual file handle
|
|||
void ConsoleListener::Close() |
|||
{ |
|||
#ifdef _WIN32
|
|||
if (hConsole == nullptr) |
|||
return; |
|||
FreeConsole(); |
|||
hConsole = nullptr; |
|||
#else
|
|||
fflush(nullptr); |
|||
#endif
|
|||
} |
|||
|
|||
bool ConsoleListener::IsOpen() |
|||
{ |
|||
#ifdef _WIN32
|
|||
return (hConsole != nullptr); |
|||
#else
|
|||
return true; |
|||
#endif
|
|||
} |
|||
|
|||
/*
|
|||
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are |
|||
dependent on each other, that's the reason for the additional checks. |
|||
*/ |
|||
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) |
|||
{ |
|||
#ifdef _WIN32
|
|||
BOOL SB, SW; |
|||
if (BufferFirst) |
|||
{ |
|||
// Change screen buffer size
|
|||
COORD Co = {BufferWidth, BufferHeight}; |
|||
SB = SetConsoleScreenBufferSize(hConsole, Co); |
|||
// Change the screen buffer window size
|
|||
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
|||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); |
|||
} |
|||
else |
|||
{ |
|||
// Change the screen buffer window size
|
|||
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
|||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); |
|||
// Change screen buffer size
|
|||
COORD Co = {BufferWidth, BufferHeight}; |
|||
SB = SetConsoleScreenBufferSize(hConsole, Co); |
|||
} |
|||
#endif
|
|||
} |
|||
void ConsoleListener::LetterSpace(int Width, int Height) |
|||
{ |
|||
#ifdef _WIN32
|
|||
// Get console info
|
|||
CONSOLE_SCREEN_BUFFER_INFO ConInfo; |
|||
GetConsoleScreenBufferInfo(hConsole, &ConInfo); |
|||
|
|||
//
|
|||
int OldBufferWidth = ConInfo.dwSize.X; |
|||
int OldBufferHeight = ConInfo.dwSize.Y; |
|||
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left); |
|||
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top); |
|||
//
|
|||
int NewBufferWidth = Width; |
|||
int NewBufferHeight = Height; |
|||
int NewScreenWidth = NewBufferWidth - 1; |
|||
int NewScreenHeight = OldScreenHeight; |
|||
|
|||
// Width
|
|||
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1)); |
|||
// Height
|
|||
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1)); |
|||
|
|||
// Resize the window too
|
|||
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
|
|||
#endif
|
|||
} |
|||
#ifdef _WIN32
|
|||
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth) |
|||
{ |
|||
COORD Ret = {0, 0}; |
|||
// Full rows
|
|||
int Step = (int)floor((float)BytesRead / (float)BufferWidth); |
|||
Ret.Y += Step; |
|||
// Partial row
|
|||
Ret.X = BytesRead - (BufferWidth * Step); |
|||
return Ret; |
|||
} |
|||
#endif
|
|||
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize) |
|||
{ |
|||
#ifdef _WIN32
|
|||
// Check size
|
|||
if (Width < 8 || Height < 12) return; |
|||
|
|||
bool DBef = true; |
|||
bool DAft = true; |
|||
std::string SLog = ""; |
|||
|
|||
const HWND hWnd = GetConsoleWindow(); |
|||
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
|
|||
// Get console info
|
|||
CONSOLE_SCREEN_BUFFER_INFO ConInfo; |
|||
GetConsoleScreenBufferInfo(hConsole, &ConInfo); |
|||
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y; |
|||
|
|||
// ---------------------------------------------------------------------
|
|||
// Save the current text
|
|||
// ------------------------
|
|||
DWORD cCharsRead = 0; |
|||
COORD coordScreen = { 0, 0 }; |
|||
|
|||
static const int MAX_BYTES = 1024 * 16; |
|||
|
|||
std::vector<std::array<TCHAR, MAX_BYTES>> Str; |
|||
std::vector<std::array<WORD, MAX_BYTES>> Attr; |
|||
|
|||
// ReadConsoleOutputAttribute seems to have a limit at this level
|
|||
static const int ReadBufferSize = MAX_BYTES - 32; |
|||
|
|||
DWORD cAttrRead = ReadBufferSize; |
|||
DWORD BytesRead = 0; |
|||
while (BytesRead < BufferSize) |
|||
{ |
|||
Str.resize(Str.size() + 1); |
|||
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead)) |
|||
SLog += Common::StringFromFormat("WriteConsoleOutputCharacter error"); |
|||
|
|||
Attr.resize(Attr.size() + 1); |
|||
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead)) |
|||
SLog += Common::StringFromFormat("WriteConsoleOutputAttribute error"); |
|||
|
|||
// Break on error
|
|||
if (cAttrRead == 0) break; |
|||
BytesRead += cAttrRead; |
|||
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X); |
|||
} |
|||
// Letter space
|
|||
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f); |
|||
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f); |
|||
int LBufWidth = LWidth + 1; |
|||
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth); |
|||
// Change screen buffer size
|
|||
LetterSpace(LBufWidth, LBufHeight); |
|||
|
|||
|
|||
ClearScreen(true); |
|||
coordScreen.Y = 0; |
|||
coordScreen.X = 0; |
|||
DWORD cCharsWritten = 0; |
|||
|
|||
int BytesWritten = 0; |
|||
DWORD cAttrWritten = 0; |
|||
for (size_t i = 0; i < Attr.size(); i++) |
|||
{ |
|||
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten)) |
|||
SLog += Common::StringFromFormat("WriteConsoleOutputCharacter error"); |
|||
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten)) |
|||
SLog += Common::StringFromFormat("WriteConsoleOutputAttribute error"); |
|||
|
|||
BytesWritten += cAttrWritten; |
|||
coordScreen = GetCoordinates(BytesWritten, LBufWidth); |
|||
} |
|||
|
|||
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; |
|||
COORD Coo = GetCoordinates(OldCursor, LBufWidth); |
|||
SetConsoleCursorPosition(hConsole, Coo); |
|||
|
|||
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str()); |
|||
|
|||
// Resize the window too
|
|||
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true); |
|||
#endif
|
|||
} |
|||
|
|||
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) |
|||
{ |
|||
#if defined(_WIN32)
|
|||
WORD Color; |
|||
|
|||
switch (Level) |
|||
{ |
|||
case OS_LEVEL: // light yellow
|
|||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; |
|||
break; |
|||
case NOTICE_LEVEL: // light green
|
|||
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY; |
|||
break; |
|||
case ERROR_LEVEL: // light red
|
|||
Color = FOREGROUND_RED | FOREGROUND_INTENSITY; |
|||
break; |
|||
case WARNING_LEVEL: // light purple
|
|||
Color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; |
|||
break; |
|||
case INFO_LEVEL: // cyan
|
|||
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; |
|||
break; |
|||
case DEBUG_LEVEL: // gray
|
|||
Color = FOREGROUND_INTENSITY; |
|||
break; |
|||
default: // off-white
|
|||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; |
|||
break; |
|||
} |
|||
SetConsoleTextAttribute(hConsole, Color); |
|||
printf(Text); |
|||
#else
|
|||
char ColorAttr[16] = ""; |
|||
char ResetAttr[16] = ""; |
|||
|
|||
if (bUseColor) |
|||
{ |
|||
strcpy(ResetAttr, "\033[0m"); |
|||
switch (Level) |
|||
{ |
|||
case NOTICE_LEVEL: // light green
|
|||
strcpy(ColorAttr, "\033[92m"); |
|||
break; |
|||
case ERROR_LEVEL: // light red
|
|||
strcpy(ColorAttr, "\033[91m"); |
|||
break; |
|||
case WARNING_LEVEL: // light yellow
|
|||
strcpy(ColorAttr, "\033[93m"); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr); |
|||
#endif
|
|||
} |
|||
// Clear console screen
|
|||
void ConsoleListener::ClearScreen(bool Cursor) |
|||
{ |
|||
#if defined(_WIN32)
|
|||
COORD coordScreen = { 0, 0 }; |
|||
DWORD cCharsWritten; |
|||
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|||
DWORD dwConSize; |
|||
|
|||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|||
|
|||
GetConsoleScreenBufferInfo(hConsole, &csbi); |
|||
dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
|||
// Write space to the entire console
|
|||
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); |
|||
GetConsoleScreenBufferInfo(hConsole, &csbi); |
|||
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); |
|||
// Reset cursor
|
|||
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); |
|||
#endif
|
|||
} |
|||
|
|||
|
|||
@ -1,38 +0,0 @@ |
|||
// Copyright 2013 Dolphin Emulator Project |
|||
// Licensed under GPLv2 |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/log_manager.h" |
|||
|
|||
#ifdef _WIN32 |
|||
#include <windows.h> |
|||
#endif |
|||
|
|||
class ConsoleListener : public LogListener |
|||
{ |
|||
public: |
|||
ConsoleListener(); |
|||
~ConsoleListener(); |
|||
|
|||
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console"); |
|||
void UpdateHandle(); |
|||
void Close(); |
|||
bool IsOpen(); |
|||
void LetterSpace(int Width, int Height); |
|||
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst); |
|||
void PixelSpace(int Left, int Top, int Width, int Height, bool); |
|||
#ifdef _WIN32 |
|||
COORD GetCoordinates(int BytesRead, int BufferWidth); |
|||
#endif |
|||
void Log(LogTypes::LOG_LEVELS, const char *Text) override; |
|||
void ClearScreen(bool Cursor = true); |
|||
|
|||
private: |
|||
#ifdef _WIN32 |
|||
HWND GetHwnd(void); |
|||
HANDLE hConsole; |
|||
#endif |
|||
bool bUseColor; |
|||
}; |
|||
@ -1,198 +0,0 @@ |
|||
// Copyright 2013 Dolphin Emulator Project
|
|||
// Licensed under GPLv2
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <algorithm>
|
|||
|
|||
#include "common/log_manager.h"
|
|||
#include "common/console_listener.h"
|
|||
#include "common/timer.h"
|
|||
|
|||
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, |
|||
const char* function, const char* fmt, ...) |
|||
{ |
|||
va_list args; |
|||
va_start(args, fmt); |
|||
|
|||
if (LogManager::GetInstance()) { |
|||
LogManager::GetInstance()->Log(level, type, |
|||
file, line, function, fmt, args); |
|||
} |
|||
va_end(args); |
|||
} |
|||
|
|||
LogManager *LogManager::m_logManager = nullptr; |
|||
|
|||
LogManager::LogManager() |
|||
{ |
|||
// create log files
|
|||
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); |
|||
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); |
|||
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common"); |
|||
m_Log[LogTypes::CONFIG] = new LogContainer("CONFIG", "Configuration"); |
|||
//m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
|
|||
//m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
|
|||
//m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
|
|||
//m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
|
|||
//m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
|
|||
//m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
|
|||
//m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
|
|||
//m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
|
|||
m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap"); |
|||
//m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
|
|||
//m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
|
|||
//m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
|
|||
//m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
|
|||
m_Log[LogTypes::GSP] = new LogContainer("GSP", "GSP"); |
|||
//m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
|
|||
//m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
|
|||
//m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
|
|||
m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11"); |
|||
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE"); |
|||
//m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
|
|||
//m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
|
|||
//m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
|
|||
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend"); |
|||
//m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
|
|||
//m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "JIT");
|
|||
//m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
|
|||
//m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
|
|||
m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing"); |
|||
m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader"); |
|||
m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System"); |
|||
//m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
|
|||
m_Log[LogTypes::KERNEL] = new LogContainer("KERNEL", "KERNEL HLE"); |
|||
//m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
|
|||
//m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
|
|||
//m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO");
|
|||
m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER"); |
|||
m_Log[LogTypes::GPU] = new LogContainer("GPU", "GPU"); |
|||
m_Log[LogTypes::SVC] = new LogContainer("SVC", "Supervisor Call HLE"); |
|||
m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation"); |
|||
m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware"); |
|||
//m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
|
|||
//m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
|
|||
//m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
|
|||
m_Log[LogTypes::GUI] = new LogContainer("GUI", "GUI"); |
|||
|
|||
m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str()); |
|||
m_consoleLog = new ConsoleListener(); |
|||
m_debuggerLog = new DebuggerLogListener(); |
|||
|
|||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) |
|||
{ |
|||
m_Log[i]->SetEnable(true); |
|||
m_Log[i]->AddListener(m_fileLog); |
|||
m_Log[i]->AddListener(m_consoleLog); |
|||
#ifdef _MSC_VER
|
|||
if (IsDebuggerPresent()) |
|||
m_Log[i]->AddListener(m_debuggerLog); |
|||
#endif
|
|||
} |
|||
|
|||
m_consoleLog->Open(); |
|||
} |
|||
|
|||
LogManager::~LogManager() |
|||
{ |
|||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) |
|||
{ |
|||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); |
|||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); |
|||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); |
|||
} |
|||
|
|||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) |
|||
delete m_Log[i]; |
|||
|
|||
delete m_fileLog; |
|||
delete m_consoleLog; |
|||
delete m_debuggerLog; |
|||
} |
|||
|
|||
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, |
|||
int line, const char* function, const char *fmt, va_list args) |
|||
{ |
|||
char temp[MAX_MSGLEN]; |
|||
char msg[MAX_MSGLEN * 2]; |
|||
LogContainer *log = m_Log[type]; |
|||
|
|||
if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners()) |
|||
return; |
|||
|
|||
Common::CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args); |
|||
|
|||
static const char level_to_char[7] = "ONEWID"; |
|||
sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line, |
|||
level_to_char[(int)level], log->GetShortName(), function, temp); |
|||
|
|||
#ifdef ANDROID
|
|||
Host_SysMessage(msg); |
|||
#endif
|
|||
log->Trigger(level, msg); |
|||
} |
|||
|
|||
void LogManager::Init() |
|||
{ |
|||
m_logManager = new LogManager(); |
|||
} |
|||
|
|||
void LogManager::Shutdown() |
|||
{ |
|||
delete m_logManager; |
|||
m_logManager = nullptr; |
|||
} |
|||
|
|||
LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable) |
|||
: m_enable(enable) |
|||
{ |
|||
strncpy(m_fullName, fullName, 128); |
|||
strncpy(m_shortName, shortName, 32); |
|||
m_level = LogTypes::MAX_LOGLEVEL; |
|||
} |
|||
|
|||
// LogContainer
|
|||
void LogContainer::AddListener(LogListener *listener) |
|||
{ |
|||
std::lock_guard<std::mutex> lk(m_listeners_lock); |
|||
m_listeners.insert(listener); |
|||
} |
|||
|
|||
void LogContainer::RemoveListener(LogListener *listener) |
|||
{ |
|||
std::lock_guard<std::mutex> lk(m_listeners_lock); |
|||
m_listeners.erase(listener); |
|||
} |
|||
|
|||
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg) |
|||
{ |
|||
std::lock_guard<std::mutex> lk(m_listeners_lock); |
|||
|
|||
std::set<LogListener*>::const_iterator i; |
|||
for (i = m_listeners.begin(); i != m_listeners.end(); ++i) |
|||
{ |
|||
(*i)->Log(level, msg); |
|||
} |
|||
} |
|||
|
|||
FileLogListener::FileLogListener(const char *filename) |
|||
{ |
|||
OpenFStream(m_logfile, filename, std::ios::app); |
|||
SetEnable(true); |
|||
} |
|||
|
|||
void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) |
|||
{ |
|||
if (!IsEnabled() || !IsValid()) |
|||
return; |
|||
|
|||
std::lock_guard<std::mutex> lk(m_log_lock); |
|||
m_logfile << msg << std::flush; |
|||
} |
|||
|
|||
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) |
|||
{ |
|||
#if _MSC_VER
|
|||
::OutputDebugStringA(msg); |
|||
#endif
|
|||
} |
|||
@ -1,166 +0,0 @@ |
|||
// Copyright 2013 Dolphin Emulator Project |
|||
// Licensed under GPLv2 |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/log.h" |
|||
#include "common/string_util.h" |
|||
#include "common/file_util.h" |
|||
|
|||
#include <cstring> |
|||
#include <set> |
|||
#include <mutex> |
|||
|
|||
#define MAX_MESSAGES 8000 |
|||
#define MAX_MSGLEN 1024 |
|||
|
|||
|
|||
// pure virtual interface |
|||
class LogListener |
|||
{ |
|||
public: |
|||
virtual ~LogListener() {} |
|||
|
|||
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0; |
|||
}; |
|||
|
|||
class FileLogListener : public LogListener |
|||
{ |
|||
public: |
|||
FileLogListener(const char *filename); |
|||
|
|||
void Log(LogTypes::LOG_LEVELS, const char *msg) override; |
|||
|
|||
bool IsValid() { return !m_logfile.fail(); } |
|||
bool IsEnabled() const { return m_enable; } |
|||
void SetEnable(bool enable) { m_enable = enable; } |
|||
|
|||
const char* GetName() const { return "file"; } |
|||
|
|||
private: |
|||
std::mutex m_log_lock; |
|||
std::ofstream m_logfile; |
|||
bool m_enable; |
|||
}; |
|||
|
|||
class DebuggerLogListener : public LogListener |
|||
{ |
|||
public: |
|||
void Log(LogTypes::LOG_LEVELS, const char *msg) override; |
|||
}; |
|||
|
|||
class LogContainer |
|||
{ |
|||
public: |
|||
LogContainer(const char* shortName, const char* fullName, bool enable = false); |
|||
|
|||
const char* GetShortName() const { return m_shortName; } |
|||
const char* GetFullName() const { return m_fullName; } |
|||
|
|||
void AddListener(LogListener* listener); |
|||
void RemoveListener(LogListener* listener); |
|||
|
|||
void Trigger(LogTypes::LOG_LEVELS, const char *msg); |
|||
|
|||
bool IsEnabled() const { return m_enable; } |
|||
void SetEnable(bool enable) { m_enable = enable; } |
|||
|
|||
LogTypes::LOG_LEVELS GetLevel() const { return m_level; } |
|||
|
|||
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; } |
|||
|
|||
bool HasListeners() const { return !m_listeners.empty(); } |
|||
|
|||
private: |
|||
char m_fullName[128]; |
|||
char m_shortName[32]; |
|||
bool m_enable; |
|||
LogTypes::LOG_LEVELS m_level; |
|||
std::mutex m_listeners_lock; |
|||
std::set<LogListener*> m_listeners; |
|||
}; |
|||
|
|||
class ConsoleListener; |
|||
|
|||
class LogManager : NonCopyable |
|||
{ |
|||
private: |
|||
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; |
|||
FileLogListener *m_fileLog; |
|||
ConsoleListener *m_consoleLog; |
|||
DebuggerLogListener *m_debuggerLog; |
|||
static LogManager *m_logManager; // Singleton. Ugh. |
|||
|
|||
LogManager(); |
|||
~LogManager(); |
|||
public: |
|||
|
|||
static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; } |
|||
|
|||
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, |
|||
const char* function, const char *fmt, va_list args); |
|||
|
|||
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) |
|||
{ |
|||
m_Log[type]->SetLevel(level); |
|||
} |
|||
|
|||
void SetEnable(LogTypes::LOG_TYPE type, bool enable) |
|||
{ |
|||
m_Log[type]->SetEnable(enable); |
|||
} |
|||
|
|||
bool IsEnabled(LogTypes::LOG_TYPE type) const |
|||
{ |
|||
return m_Log[type]->IsEnabled(); |
|||
} |
|||
|
|||
const char* GetShortName(LogTypes::LOG_TYPE type) const |
|||
{ |
|||
return m_Log[type]->GetShortName(); |
|||
} |
|||
|
|||
const char* GetFullName(LogTypes::LOG_TYPE type) const |
|||
{ |
|||
return m_Log[type]->GetFullName(); |
|||
} |
|||
|
|||
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener) |
|||
{ |
|||
m_Log[type]->AddListener(listener); |
|||
} |
|||
|
|||
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener) |
|||
{ |
|||
m_Log[type]->RemoveListener(listener); |
|||
} |
|||
|
|||
FileLogListener *GetFileListener() const |
|||
{ |
|||
return m_fileLog; |
|||
} |
|||
|
|||
ConsoleListener *GetConsoleListener() const |
|||
{ |
|||
return m_consoleLog; |
|||
} |
|||
|
|||
DebuggerLogListener *GetDebuggerListener() const |
|||
{ |
|||
return m_debuggerLog; |
|||
} |
|||
|
|||
static LogManager* GetInstance() |
|||
{ |
|||
return m_logManager; |
|||
} |
|||
|
|||
static void SetInstance(LogManager *logManager) |
|||
{ |
|||
m_logManager = logManager; |
|||
} |
|||
|
|||
static void Init(); |
|||
static void Shutdown(); |
|||
}; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue