| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-03-28 08:57:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-20 04:11:52 +01:00
										 |  |  | #include <cstdarg>
 | 
					
						
							|  |  |  | #include <cstring>
 | 
					
						
							|  |  |  | #include <mutex>
 | 
					
						
							|  |  |  | #include <ostream>
 | 
					
						
							|  |  |  | #include <set>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2010-05-28 23:14:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | #ifdef ANDROID
 | 
					
						
							| 
									
										
										
										
											2014-11-05 02:22:33 -05:00
										 |  |  | #include <android/log.h>
 | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "Common/FileUtil.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-03 19:48:54 -04:00
										 |  |  | #include "Common/IniFile.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-20 04:11:52 +01:00
										 |  |  | #include "Common/StringUtil.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-19 01:54:11 +01:00
										 |  |  | #include "Common/Timer.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-05 19:29:54 -04:00
										 |  |  | #include "Common/Logging/ConsoleListener.h"
 | 
					
						
							|  |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							|  |  |  | #include "Common/Logging/LogManager.h"
 | 
					
						
							| 
									
										
										
										
											2010-01-19 19:28:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, | 
					
						
							| 
									
										
										
										
											2010-07-16 19:08:26 +00:00
										 |  |  | 		const char *file, int line, const char* fmt, ...) | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	va_list args; | 
					
						
							|  |  |  | 	va_start(args, fmt); | 
					
						
							| 
									
										
										
										
											2010-02-16 04:34:41 +00:00
										 |  |  | 	if (LogManager::GetInstance()) | 
					
						
							| 
									
										
										
										
											2010-07-16 19:08:26 +00:00
										 |  |  | 		LogManager::GetInstance()->Log(level, type, | 
					
						
							|  |  |  | 			file, line, fmt, args); | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | 	va_end(args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | LogManager *LogManager::m_logManager = nullptr; | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | LogManager::LogManager() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	// create log files
 | 
					
						
							| 
									
										
										
										
											2014-02-16 23:51:41 -05:00
										 |  |  | 	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::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::GPFIFO]             = new LogContainer("GP",              "GPFifo"); | 
					
						
							|  |  |  | 	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::POWERPC]            = new LogContainer("PowerPC",         "IBM CPU"); | 
					
						
							|  |  |  | 	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",             "Dynamic Recompiler"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::CONSOLE]            = new LogContainer("CONSOLE",         "Dolphin Console"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::OSREPORT]           = new LogContainer("OSREPORT",        "OSReport"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WIIMOTE]            = new LogContainer("Wiimote",         "Wiimote"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC]            = new LogContainer("WII_IPC",         "WII IPC"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_HID]        = new LogContainer("WII_IPC_HID",     "WII IPC HID"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_HLE]        = new LogContainer("WII_IPC_HLE",     "WII IPC 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::WII_IPC_SD]         = new LogContainer("WII_IPC_SD",      "WII IPC SD"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_STM]        = new LogContainer("WII_IPC_STM",     "WII IPC STM"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_NET]        = new LogContainer("WII_IPC_NET",     "WII IPC NET"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_WC24]       = new LogContainer("WII_IPC_WC24",    "WII IPC WC24"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_SSL]        = new LogContainer("WII_IPC_SSL",     "WII IPC SSL"); | 
					
						
							|  |  |  | 	m_Log[LogTypes::WII_IPC_WIIMOTE]    = new LogContainer("WII_IPC_WIIMOTE", "WII IPC WIIMOTE"); | 
					
						
							|  |  |  | 	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"); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-05 18:24:10 -04:00
										 |  |  | 	m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX)); | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | 	m_consoleLog = new ConsoleListener(); | 
					
						
							|  |  |  | 	m_debuggerLog = new DebuggerLogListener(); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-03 19:48:54 -04:00
										 |  |  | 	IniFile ini; | 
					
						
							|  |  |  | 	ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX)); | 
					
						
							|  |  |  | 	IniFile::Section* logs = ini.GetOrCreateSection("Logs"); | 
					
						
							| 
									
										
										
										
											2014-02-12 16:00:34 +01:00
										 |  |  | 	for (LogContainer* container : m_Log) | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-03 19:48:54 -04:00
										 |  |  | 		bool enable; | 
					
						
							|  |  |  | 		logs->Get(container->GetShortName(), &enable, false); | 
					
						
							|  |  |  | 		container->SetEnable(enable); | 
					
						
							|  |  |  | 		if (enable) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			container->AddListener(m_fileLog); | 
					
						
							|  |  |  | 			container->AddListener(m_consoleLog); | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | #ifdef _MSC_VER
 | 
					
						
							| 
									
										
										
										
											2014-09-03 19:48:54 -04:00
										 |  |  | 			if (IsDebuggerPresent()) | 
					
						
							|  |  |  | 				container->AddListener(m_debuggerLog); | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-09-03 19:48:54 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | LogManager::~LogManager() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | 		m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); | 
					
						
							|  |  |  | 		m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-02-16 04:34:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-12 16:00:34 +01:00
										 |  |  | 	for (LogContainer* container : m_Log) | 
					
						
							| 
									
										
										
										
											2013-10-29 01:09:01 -04:00
										 |  |  | 		delete container; | 
					
						
							| 
									
										
										
										
											2010-02-16 04:34:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	delete m_fileLog; | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | 	delete m_consoleLog; | 
					
						
							|  |  |  | 	delete m_debuggerLog; | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	const char *file, int line, const char *format, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	char temp[MAX_MSGLEN]; | 
					
						
							|  |  |  | 	LogContainer *log = m_Log[type]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners()) | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	CharArrayFromFormatV(temp, MAX_MSGLEN, format, args); | 
					
						
							| 
									
										
										
										
											2009-03-20 21:23:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 14:23:34 +13:00
										 |  |  | 	std::string msg = StringFromFormat("%s %s:%u %c[%s]: %s\n", | 
					
						
							|  |  |  | 	                                   Common::Timer::GetTimeFormatted().c_str(), | 
					
						
							| 
									
										
										
										
											2014-03-29 11:05:44 +01:00
										 |  |  | 	                                   file, line, | 
					
						
							| 
									
										
										
										
											2014-02-08 14:23:34 +13:00
										 |  |  | 	                                   LogTypes::LOG_LEVEL_TO_CHAR[(int)level], | 
					
						
							| 
									
										
										
										
											2014-06-05 18:24:10 -04:00
										 |  |  | 	                                   log->GetShortName().c_str(), temp); | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | #ifdef ANDROID
 | 
					
						
							| 
									
										
										
										
											2014-11-05 02:22:33 -05:00
										 |  |  | 	__android_log_write(ANDROID_LOG_INFO, "Dolphinemu", msg.c_str()); | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-08 14:23:34 +13:00
										 |  |  | 	log->Trigger(level, msg.c_str()); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-16 04:34:41 +00:00
										 |  |  | void LogManager::Init() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_logManager = new LogManager(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void LogManager::Shutdown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	delete m_logManager; | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 	m_logManager = nullptr; | 
					
						
							| 
									
										
										
										
											2010-02-16 04:34:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-05 18:24:10 -04:00
										 |  |  | LogContainer::LogContainer(const std::string& shortName, const std::string& fullName, bool enable) | 
					
						
							|  |  |  | 	: m_fullName(fullName), | 
					
						
							|  |  |  | 	  m_shortName(shortName), | 
					
						
							|  |  |  | 	  m_enable(enable), | 
					
						
							|  |  |  | 	  m_level(LogTypes::LWARNING) | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-20 20:52:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | // LogContainer
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | void LogContainer::AddListener(LogListener *listener) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::lock_guard<std::mutex> lk(m_listeners_lock); | 
					
						
							|  |  |  | 	m_listeners.insert(listener); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | void LogContainer::RemoveListener(LogListener *listener) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::lock_guard<std::mutex> lk(m_listeners_lock); | 
					
						
							|  |  |  | 	m_listeners.erase(listener); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::lock_guard<std::mutex> lk(m_listeners_lock); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-12 16:00:34 +01:00
										 |  |  | 	for (LogListener* listener : m_listeners) | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-12 16:00:34 +01:00
										 |  |  | 		listener->Log(level, msg); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-05 18:24:10 -04:00
										 |  |  | FileLogListener::FileLogListener(const std::string& filename) | 
					
						
							| 
									
										
										
										
											2011-03-11 10:21:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-28 19:33:39 -06:00
										 |  |  | 	OpenFStream(m_logfile, filename, std::ios::app); | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	SetEnable(true); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-11 10:21:46 +00:00
										 |  |  | void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	if (!IsEnabled() || !IsValid()) | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-01 07:43:02 +00:00
										 |  |  | 	std::lock_guard<std::mutex> lk(m_log_lock); | 
					
						
							| 
									
										
										
										
											2011-03-11 10:21:46 +00:00
										 |  |  | 	m_logfile << msg << std::flush; | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-23 07:33:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if _MSC_VER
 | 
					
						
							|  |  |  | 	::OutputDebugStringA(msg); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } |