Merge branch 'new-log'

This commit is contained in:
David Capello 2016-02-26 17:11:51 -03:00
commit bc9c3b0ec2
9 changed files with 199 additions and 65 deletions

View File

@ -109,8 +109,8 @@ public:
// This is a raw pointer because we want to delete this explicitly.
app::crash::DataRecovery* m_recovery;
Modules(bool verbose)
: m_loggerModule(verbose)
Modules(bool createLogInDesktop)
: m_loggerModule(createLogInDesktop)
, m_recovery(nullptr) {
}
@ -164,10 +164,23 @@ void App::initialize(const AppOptions& options)
if (m_isGui)
m_uiSystem.reset(new ui::UISystem);
// Initializes the application loading the modules, setting the
// graphics mode, loading the configuration and resources, etc.
m_coreModules = new CoreModules;
m_modules = new Modules(options.verbose());
bool createLogInDesktop = false;
switch (options.verboseLevel()) {
case AppOptions::kNoVerbose:
base::set_log_level(ERROR);
break;
case AppOptions::kVerbose:
base::set_log_level(INFO);
break;
case AppOptions::kHighlyVerbose:
base::set_log_level(VERBOSE);
createLogInDesktop = true;
break;
}
m_modules = new Modules(createLogInDesktop);
m_legacy = new LegacyModules(isGui() ? REQUIRE_INTERFACE: 0);
m_brushes.reset(new AppBrushes);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -24,7 +24,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
: m_exeName(base::get_file_name(argv[0]))
, m_startUI(true)
, m_startShell(false)
, m_verboseEnabled(false)
, m_verboseLevel(kNoVerbose)
, m_palette(m_po.add("palette").requiresValue("<filename>").description("Use a specific palette by default"))
, m_shell(m_po.add("shell").description("Start an interactive console to execute scripts"))
, m_batch(m_po.add("batch").mnemonic('b').description("Do not start the UI"))
@ -52,13 +52,18 @@ AppOptions::AppOptions(int argc, const char* argv[])
, m_listLayers(m_po.add("list-layers").description("List layers of the next given sprite\nor include layers in JSON data"))
, m_listTags(m_po.add("list-tags").description("List tags of the next given sprite sprite\nor include frame tags in JSON data"))
, m_verbose(m_po.add("verbose").mnemonic('v').description("Explain what is being done"))
, m_debug(m_po.add("debug").description("Extreme verbose mode and\ncopy log to desktop"))
, m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
, m_version(m_po.add("version").description("Output version information and exit"))
{
try {
m_po.parse(argc, argv);
m_verboseEnabled = m_po.enabled(m_verbose);
if (m_po.enabled(m_debug))
m_verboseLevel = kHighlyVerbose;
else if (m_po.enabled(m_verbose))
m_verboseLevel = kVerbose;
m_paletteFileName = m_po.value_of(m_palette);
m_startShell = m_po.enabled(m_shell);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -19,6 +19,12 @@ namespace app {
class AppOptions {
public:
enum VerboseLevel {
kNoVerbose,
kVerbose,
kHighlyVerbose,
};
typedef base::ProgramOptions PO;
typedef PO::Option Option;
typedef PO::ValueList ValueList;
@ -27,7 +33,7 @@ public:
bool startUI() const { return m_startUI; }
bool startShell() const { return m_startShell; }
bool verbose() const { return m_verboseEnabled; }
VerboseLevel verboseLevel() const { return m_verboseLevel; }
const std::string& paletteFileName() const { return m_paletteFileName; }
@ -70,7 +76,7 @@ private:
base::ProgramOptions m_po;
bool m_startUI;
bool m_startShell;
bool m_verboseEnabled;
VerboseLevel m_verboseLevel;
std::string m_paletteFileName;
Option& m_palette;
@ -101,6 +107,7 @@ private:
Option& m_listTags;
Option& m_verbose;
Option& m_debug;
Option& m_help;
Option& m_version;

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -17,19 +17,17 @@
namespace app {
static LoggerModule* logger_instance = NULL;
LoggerModule::LoggerModule(bool verbose)
: m_verbose(verbose)
LoggerModule::LoggerModule(bool createLogInDesktop)
{
logger_instance = this;
if (verbose) {
app::ResourceFinder rf(false);
if (createLogInDesktop)
rf.includeDesktopDir(PACKAGE "-v" VERSION "-DebugOutput.txt");
else
rf.includeUserDir("aseprite.log");
auto filename = rf.defaultFilename();
base_set_log_filename(filename.c_str());
}
base::set_log_filename(filename.c_str());
}
LoggerModule::~LoggerModule()
@ -37,8 +35,7 @@ LoggerModule::~LoggerModule()
LOG("Logger module: shutting down (this is the last line)\n");
// Close log file
base_set_log_filename("");
logger_instance = nullptr;
base::set_log_filename("");
}
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -13,13 +13,8 @@ namespace app {
class LoggerModule {
public:
LoggerModule(bool verbose);
LoggerModule(bool createLogInDesktop);
~LoggerModule();
bool isVerbose() const { return m_verbose; }
private:
bool m_verbose;
};
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -19,6 +19,11 @@
#include <cstdio>
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#include <shlobj.h>
#endif
namespace app {
ResourceFinder::ResourceFinder(bool log)
@ -163,6 +168,41 @@ void ResourceFinder::includeUserDir(const char* filename)
#endif
}
void ResourceFinder::includeDesktopDir(const char* filename)
{
#ifdef _WIN32
std::vector<wchar_t> buf(MAX_PATH);
HRESULT hr = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
SHGFP_TYPE_DEFAULT, &buf[0]);
if (hr == S_OK) {
addPath(base::join_path(base::to_utf8(&buf[0]), filename));
}
else {
includeHomeDir(filename);
}
#elif defined(__APPLE__)
// TODO get the desktop folder
// $HOME/Desktop/filename
includeHomeDir(base::join_path(std::string("Desktop"), filename).c_str());
#else
char* desktopDir = std::getenv("XDG_DESKTOP_DIR");
if (desktopDir) {
// $XDG_DESKTOP_DIR/filename
addPath(base::join_path(desktopDir, filename));
}
else {
// $HOME/Desktop/filename
includeHomeDir(base::join_path(std::string("Desktop"), filename).c_str());
}
#endif
}
std::string ResourceFinder::getFirstOrCreateDefault()
{
std::string fn;

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -51,6 +51,8 @@ namespace app {
// - The filename will be in $HOME/.config/aseprite/
void includeUserDir(const char* filename);
void includeDesktopDir(const char* filename);
// Returns the first file found or creates the whole directory
// structure to create the file in its default location.
std::string getFirstOrCreateDefault();

View File

@ -1,5 +1,5 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -10,47 +10,99 @@
#include "base/log.h"
#include "base/file_handle.h"
#include "base/fstream_path.h"
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
static FILE* log_fileptr = nullptr;
static std::string log_filename;
namespace {
void base_set_log_filename(const char* filename)
{
if (log_fileptr) {
fclose(log_fileptr);
log_fileptr = nullptr;
class nullbuf : public std::streambuf {
protected:
int_type overflow(int_type ch) override {
return traits_type::not_eof(ch);
}
};
class nullstream : public std::ostream {
public:
nullstream()
: std::basic_ios<char_type, traits_type>(&m_buf)
, std::ostream(&m_buf) { }
private:
nullbuf m_buf;
};
LogLevel log_level = LogLevel::NONE;
nullstream null_stream;
std::ofstream log_stream;
std::string log_filename;
bool open_log_stream()
{
if (!log_stream.is_open()) {
if (log_filename.empty())
return false;
log_stream.open(FSTREAM_PATH(log_filename));
}
return log_stream.is_open();
}
void log_text(const char* text)
{
if (!open_log_stream())
return;
log_stream.write(text, strlen(text));
log_stream.flush();
}
} // anonymous namespace
void base::set_log_filename(const char* filename)
{
if (log_stream.is_open())
log_stream.close();
log_filename = filename;
}
void base_log(const char* format, ...)
void base::set_log_level(LogLevel level)
{
if (!log_fileptr) {
if (log_filename.empty())
return;
log_fileptr = base::open_file_raw(log_filename, "w");
log_level = level;
}
if (log_fileptr) {
std::ostream& base::get_log_stream(LogLevel level)
{
ASSERT(level != NONE);
if ((log_level < level) ||
(!log_stream.is_open() && !open_log_stream()))
return null_stream;
else
return log_stream;
}
void LOG(const char* format, ...)
{
if (log_level < INFO)
return;
char buf[2048];
va_list ap;
va_start(ap, format);
vfprintf(log_fileptr, format, ap);
fflush(log_fileptr);
std::vsnprintf(buf, sizeof(buf)-1, format, ap);
log_text(buf);
#ifdef _DEBUG
va_start(ap, format);
vfprintf(stderr, format, ap);
fputs(buf, stderr);
fflush(stderr);
#endif
va_end(ap);
}
}

View File

@ -1,5 +1,5 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -8,12 +8,35 @@
#define BASE_LOG_H_INCLUDED
#pragma once
// Define BASE_DONT_DEFINE_LOG_MACRO in case that you don't need LOG
#ifndef BASE_DONT_DEFINE_LOG_MACRO
#define LOG base_log
#endif
enum LogLevel {
NONE = 0, // Default log level: do not log
FATAL = 1, // Something failed and we CANNOT continue the execution
ERROR = 2, // Something failed, the UI should show this, and we can continue
WARNING = 3, // Something failed, the UI don't need to show this, and we can continue
INFO = 4, // Information about some important event
VERBOSE = 5, // Information step by step
};
void base_set_log_filename(const char* filename);
void base_log(const char* format, ...);
// E.g. LOG("text in information log level\n");
void LOG(const char* format, ...);
#ifdef __cplusplus
#include <iosfwd>
namespace base {
void set_log_filename(const char* filename);
void set_log_level(LogLevel level);
std::ostream& get_log_stream(LogLevel level);
} // namespace base
// E.g. LOG(INFO) << "some information\n";
inline std::ostream& LOG(LogLevel level) {
return base::get_log_stream(level);
}
#endif
#endif