Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 20, 2009, 4:55:40 PM (15 years ago)
Author:
rgrieder
Message:

Merged console branch back to trunk.

Location:
code/trunk
Files:
2 deleted
29 edited
2 copied

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/core/CMakeLists.txt

    r6021 r6105  
    2929  GraphicsManager.cc
    3030  GUIManager.cc
     31  IOConsole.cc
    3132  Language.cc
    3233  LuaState.cc
  • code/trunk/src/libraries/core/ConfigFileManager.h

    r5738 r6105  
    5454    };
    5555
    56     bool config(const std::string& classname, const std::string& varname, const std::string& value);
    57     bool tconfig(const std::string& classname, const std::string& varname, const std::string& value);
    58     void reloadConfig();
    59     void saveConfig();
    60     void cleanConfig();
    61     void loadSettings(const std::string& filename);
     56    _CoreExport bool config(const std::string& classname, const std::string& varname, const std::string& value);
     57    _CoreExport bool tconfig(const std::string& classname, const std::string& varname, const std::string& value);
     58    _CoreExport void reloadConfig();
     59    _CoreExport void saveConfig();
     60    _CoreExport void cleanConfig();
     61    _CoreExport void loadSettings(const std::string& filename);
    6262
    6363
  • code/trunk/src/libraries/core/ConfigValueIncludes.h

    r5738 r6105  
    4747    @param defvalue The default-value of the variable
    4848*/
    49 #define SetConfigValueGeneric(type, varname, defvalue) \
     49#define SetConfigValueGeneric(type, varname, entryname, sectionname, defvalue) \
    5050    static orxonox::Identifier* identifier##varname = this->getIdentifier(); \
    51     orxonox::ConfigValueContainer* container##varname = identifier##varname->getConfigValueContainer(#varname); \
     51    orxonox::ConfigValueContainer* container##varname = identifier##varname->getConfigValueContainer(entryname); \
    5252    if (!container##varname) \
    5353    { \
    54         container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
    55         identifier##varname->addConfigValueContainer(#varname, container##varname); \
     54        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, sectionname, entryname, defvalue, varname); \
     55        identifier##varname->addConfigValueContainer(entryname, container##varname); \
    5656    } \
    5757    container##varname->getValue(&varname, this)
    5858
    59 #define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, defvalue)
     59#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, #varname, identifier##varname->getName(), defvalue)
    6060
    6161
  • code/trunk/src/libraries/core/ConsoleCommandCompilation.cc

    r5781 r6105  
    8686    std::string echo(const std::string& text)
    8787    {
    88         std::cout << text << std::endl;
    8988        return text;
    9089    }
  • code/trunk/src/libraries/core/Core.cc

    r6021 r6105  
    6464#include "Identifier.h"
    6565#include "Language.h"
     66#include "IOConsole.h"
    6667#include "LuaState.h"
    6768#include "ScopedSingletonManager.h"
    68 #include "Shell.h"
    6969#include "TclBind.h"
    7070#include "TclThreadManager.h"
     
    105105        void setConfigValues()
    106106        {
    107 #ifdef NDEBUG
    108             const unsigned int defaultLevelConsole = 1;
    109             const unsigned int defaultLevelLogfile = 3;
    110             const unsigned int defaultLevelShell   = 1;
     107#ifdef ORXONOX_RELEASE
     108            const unsigned int defaultLevelLogFile = 3;
    111109#else
    112             const unsigned int defaultLevelConsole = 3;
    113             const unsigned int defaultLevelLogfile = 4;
    114             const unsigned int defaultLevelShell   = 3;
    115 #endif
    116             SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
    117                 .description("The maximal level of debug output shown in the console")
    118                 .callback(this, &CoreConfiguration::debugLevelChanged);
    119             SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
    120                 .description("The maximal level of debug output shown in the logfile")
    121                 .callback(this, &CoreConfiguration::debugLevelChanged);
    122             SetConfigValue(softDebugLevelShell_, defaultLevelShell)
    123                 .description("The maximal level of debug output shown in the ingame shell")
    124                 .callback(this, &CoreConfiguration::debugLevelChanged);
     110            const unsigned int defaultLevelLogFile = 4;
     111#endif
     112            SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevelLogFile_, "softDebugLevelLogFile", "OutputHandler", defaultLevelLogFile)
     113                .description("The maximum level of debug output shown in the log file");
     114            OutputHandler::getInstance().setSoftDebugLevel(OutputHandler::logFileOutputListenerName_s, this->softDebugLevelLogFile_);
    125115
    126116            SetConfigValue(language_, Language::getInstance().defaultLanguage_)
    127                 .description("The language of the ingame text")
     117                .description("The language of the in game text")
    128118                .callback(this, &CoreConfiguration::languageChanged);
    129119            SetConfigValue(bInitializeRandomNumberGenerator_, true)
    130120                .description("If true, all random actions are different each time you start the game")
    131121                .callback(this, &CoreConfiguration::initializeRandomNumberGenerator);
    132         }
    133 
    134         /**
    135             @brief Callback function if the debug level has changed.
    136         */
    137         void debugLevelChanged()
    138         {
    139             // softDebugLevel_ is the maximum of the 3 variables
    140             this->softDebugLevel_ = this->softDebugLevelConsole_;
    141             if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
    142                 this->softDebugLevel_ = this->softDebugLevelLogfile_;
    143             if (this->softDebugLevelShell_ > this->softDebugLevel_)
    144                 this->softDebugLevel_ = this->softDebugLevelShell_;
    145 
    146             OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
    147             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
    148             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
    149             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
    150122        }
    151123
     
    178150        }
    179151
    180         int softDebugLevel_;                            //!< The debug level
    181         int softDebugLevelConsole_;                     //!< The debug level for the console
    182         int softDebugLevelLogfile_;                     //!< The debug level for the logfile
    183         int softDebugLevelShell_;                       //!< The debug level for the ingame shell
     152        int softDebugLevelLogFile_;                     //!< The debug level for the log file (belongs to OutputHandler)
    184153        std::string language_;                          //!< The language
    185154        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
     
    221190        this->pathConfig_->setConfigurablePaths();
    222191
    223         // create a signal handler (only active for linux)
     192        // create a signal handler (only active for Linux)
    224193        // This call is placed as soon as possible, but after the directories are set
    225194        this->signalHandler_.reset(new SignalHandler());
    226195        this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
    227196
    228         // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    229         OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
     197        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% (Windows) was used
     198        OutputHandler::getInstance().setLogPath(PathConfig::getLogPathString());
    230199
    231200        // Parse additional options file now that we know its path
     
    249218        this->languageInstance_.reset(new Language());
    250219
     220        // create persistent io console
     221        this->ioConsole_.reset(new IOConsole());
     222
    251223        // creates the class hierarchy for all classes with factories
    252224        Identifier::createClassHierarchy();
     
    262234        this->tclBind_.reset(new TclBind(PathConfig::getDataPathString()));
    263235        this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter()));
    264 
    265         // create a shell
    266         this->shell_.reset(new Shell());
    267236
    268237        // Create singletons that always exist (in other libraries)
     
    325294        bGraphicsLoaded_ = false;
    326295        GameMode::bShowsGraphics_s = false;
    327     }
    328 
    329     /**
    330         @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
    331         @param device The device
    332         @return The softDebugLevel
    333     */
    334     /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
    335     {
    336         switch (device)
    337         {
    338         case OutputHandler::LD_All:
    339             return Core::getInstance().configuration_->softDebugLevel_;
    340         case OutputHandler::LD_Console:
    341             return Core::getInstance().configuration_->softDebugLevelConsole_;
    342         case OutputHandler::LD_Logfile:
    343             return Core::getInstance().configuration_->softDebugLevelLogfile_;
    344         case OutputHandler::LD_Shell:
    345             return Core::getInstance().configuration_->softDebugLevelShell_;
    346         default:
    347             assert(0);
    348             return 2;
    349         }
    350     }
    351 
    352      /**
    353         @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
    354         @param device The device
    355         @param level The level
    356     */
    357     /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    358     {
    359         if (device == OutputHandler::LD_All)
    360             Core::getInstance().configuration_->softDebugLevel_ = level;
    361         else if (device == OutputHandler::LD_Console)
    362             Core::getInstance().configuration_->softDebugLevelConsole_ = level;
    363         else if (device == OutputHandler::LD_Logfile)
    364             Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
    365         else if (device == OutputHandler::LD_Shell)
    366             Core::getInstance().configuration_->softDebugLevelShell_ = level;
    367 
    368         OutputHandler::setSoftDebugLevel(device, level);
    369296    }
    370297
     
    444371            ScopedSingletonManager::update<ScopeID::Graphics>(time);
    445372        }
     373        // process console text
     374        this->ioConsole_->update(time);
    446375        // process thread commands
    447376        this->tclThreadManager_->update(time);
  • code/trunk/src/libraries/core/Core.h

    r5929 r6105  
    6969            void setConfigValues();
    7070
    71             static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    72             static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    7371            static const std::string& getLanguage();
    7472            static void  resetLanguage();
     
    9391            scoped_ptr<ConfigFileManager> configFileManager_;
    9492            scoped_ptr<Language>          languageInstance_;
     93            scoped_ptr<IOConsole>         ioConsole_;
    9594            scoped_ptr<CoreConfiguration> configuration_;
    9695            scoped_ptr<TclBind>           tclBind_;
    9796            scoped_ptr<TclThreadManager>  tclThreadManager_;
    98             scoped_ptr<Shell>             shell_;
    9997            // graphical
    10098            scoped_ptr<GraphicsManager>   graphicsManager_;     //!< Interface to OGRE
  • code/trunk/src/libraries/core/CorePrereqs.h

    r6021 r6105  
    148148    class GUIManager;
    149149    class Identifier;
     150    class IOConsole;
    150151    class IRC;
    151152    template <class T>
  • code/trunk/src/libraries/core/GUIManager.cc

    r5929 r6105  
    5353#include "util/Exception.h"
    5454#include "util/OrxAssert.h"
    55 #include "Core.h"
    5655#include "LuaState.h"
    5756#include "PathConfig.h"
     
    7574                default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
    7675            }
    77             OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
     76            OutputHandler::getOutStream(orxonoxLevel)
    7877                << "CEGUI: " << message << std::endl;
    7978
     
    121120        // set the log level according to ours (translate by subtracting 1)
    122121        ceguiLogger->setLoggingLevel(
    123             static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
     122            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
    124123        this->ceguiLogger_ = ceguiLogger.release();
    125124
     
    127126        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
    128127
    129         // Initialise the basic lua code
     128        // Initialise the basic Lua code
    130129        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua", "GUI");
    131130        this->luaState_->doFile("InitialiseGUI.lua", "GUI", false);
     
    134133        guiSystem_->injectMousePosition(mousePosition.first, mousePosition.second);
    135134
    136         // Hide the mouse cursor unless playing in fullscreen mode
     135        // Hide the mouse cursor unless playing in full screen mode
    137136        if (!bFullScreen)
    138137            CEGUI::MouseCursor::getSingleton().hide();
     
    280279        code of the mouse button as it is used by CEGUI
    281280
    282         Simple convertion from mouse event code in Orxonox to the one used in CEGUI.
     281        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
    283282     */
    284283    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
  • code/trunk/src/libraries/core/GraphicsManager.cc

    r6075 r6105  
    409409            orxonoxLevel = 0;
    410410        }
    411         OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
     411        OutputHandler::getOutStream(orxonoxLevel)
    412412            << "Ogre: " << message << std::endl;
    413413    }
  • code/trunk/src/libraries/core/GraphicsManager.h

    r5929 r6105  
    106106
    107107        // config values
    108         std::string         ogreConfigFile_;           //!< ogre config file name
     108        std::string         ogreConfigFile_;           //!< ogre config filename
    109109        std::string         ogrePluginsDirectory_;     //!< Directory where the Ogre plugins are located
    110110        std::string         ogrePlugins_;              //!< Comma separated list of all plugins to load
    111         std::string         ogreLogFile_;              //!< log file name for Ogre log messages
    112         int                 ogreLogLevelTrivial_;      //!< Corresponding Orxonx debug level for LL_TRIVIAL
    113         int                 ogreLogLevelNormal_;       //!< Corresponding Orxonx debug level for LL_NORMAL
    114         int                 ogreLogLevelCritical_;     //!< Corresponding Orxonx debug level for LL_CRITICAL
     111        std::string         ogreLogFile_;              //!< log filename for Ogre log messages
     112        int                 ogreLogLevelTrivial_;      //!< Corresponding Orxonox debug level for LL_TRIVIAL
     113        int                 ogreLogLevelNormal_;       //!< Corresponding Orxonox debug level for LL_NORMAL
     114        int                 ogreLogLevelCritical_;     //!< Corresponding Orxonox debug level for LL_CRITICAL
    115115
    116116        // console commands
  • code/trunk/src/libraries/core/IOConsole.cc

    r6103 r6105  
    160160        // Erase input and status lines
    161161        this->cout_ << "\033[1G\033[J";
     162        // Move cursor to the bottom
     163        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
     164        // Scroll terminal to compensate for erased lines
     165        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'T';
    162166
    163167        resetTerminalMode();
  • code/trunk/src/libraries/core/LuaState.cc

    r5929 r6105  
    182182    void LuaState::luaLog(unsigned int level, const std::string& message)
    183183    {
    184         OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
     184        OutputHandler::getOutStream(level) << message << std::endl;
    185185    }
    186186
  • code/trunk/src/libraries/core/OrxonoxClass.cc

    r5929 r6105  
    3434#include "OrxonoxClass.h"
    3535
     36#include <cassert>
    3637#include "MetaObjectList.h"
    3738#include "Identifier.h"
     
    7273    void OrxonoxClass::destroy()
    7374    {
     75        assert(this); // Just in case someone tries to delete a NULL pointer
    7476        this->requestedDestruction_ = true;
    7577        if (this->referenceCount_ == 0)
  • code/trunk/src/libraries/core/OrxonoxClass.h

    r5929 r6105  
    4242#include <set>
    4343#include <vector>
     44
     45/**
     46@def CCOUT
     47    Acts almost exactly like COUT(x), but prepends "ClassName: "
     48*/
     49#define CCOUT(level) \
     50    COUT(level) << this->getIdentifier()->getName() << ": "
    4451
    4552namespace orxonox
  • code/trunk/src/libraries/core/PathConfig.cc

    r6021 r6105  
    263263        putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + modulePath_.string()).c_str()));
    264264
     265        // Make sure the path exists, otherwise don't load modules
     266        if (!boost::filesystem::exists(modulePath_))
     267            return modulePaths;
     268
    265269        boost::filesystem::directory_iterator file(modulePath_);
    266270        boost::filesystem::directory_iterator end;
  • code/trunk/src/libraries/core/Shell.cc

    r5929 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
     
    3030
    3131#include "util/OutputHandler.h"
     32#include "util/StringUtils.h"
     33#include "util/SubString.h"
    3234#include "CommandExecutor.h"
    3335#include "CoreIncludes.h"
    3436#include "ConfigValueIncludes.h"
    35 #include "Core.h"
    3637#include "ConsoleCommand.h"
    37 
    38 #define SHELL_UPDATE_LISTENERS(function) \
    39     for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ) \
    40         (*(it++))->function()
    4138
    4239namespace orxonox
    4340{
    44     SetConsoleCommand(Shell, clearShell, true);
    45     SetConsoleCommand(Shell, history, true);
    46 
    4741    SetConsoleCommandShortcut(OutputHandler, log);
    4842    SetConsoleCommandShortcut(OutputHandler, error);
     
    5145    SetConsoleCommandShortcut(OutputHandler, debug);
    5246
    53     Shell* Shell::singletonPtr_s = 0;
    54 
    55     Shell::Shell()
    56     {
    57         int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell);
    58         Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
    59 
     47    Shell::Shell(const std::string& consoleName, bool bScrollable, bool bPrependOutputLevel)
     48        : OutputListener(consoleName)
     49        , inputBuffer_(new InputBuffer())
     50        , consoleName_(consoleName)
     51        , bPrependOutputLevel_(bPrependOutputLevel)
     52        , bScrollable_(bScrollable)
     53    {
    6054        RegisterRootObject(Shell);
    6155
     
    6458        this->historyPosition_ = 0;
    6559        this->historyOffset_ = 0;
    66         this->finishedLastLine_ = true;
    67         this->bAddOutputLevel_ = false;
    68 
    69         this->clearLines();
    70 
    71         this->inputBuffer_ = new InputBuffer();
     60        this->bFinishedLastLine_ = true;
     61
     62        this->clearOutput();
    7263        this->configureInputBuffer();
    73 
    74         this->outputBuffer_.registerListener(this);
    75         OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);
    7664
    7765        // Get a config file for the command history
     
    7967        ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini");
    8068
     69        // Use a stringstream object to buffer the output and get it line by line in update()
     70        this->outputStream_ = &this->outputBuffer_;
     71
    8172        this->setConfigValues();
    8273
    83         Core::setSoftDebugLevel(OutputHandler::LD_Shell, level);
     74        // Get the previous output and add it to the Shell
     75        for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
     76            it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
     77        {
     78            if (it->first <= this->getSoftDebugLevel())
     79            {
     80                this->outputBuffer_ << it->second;
     81                this->outputChanged(it->first);
     82            }
     83        }
     84
     85        // Register the shell as output listener
     86        OutputHandler::getInstance().registerOutputListener(this);
    8487    }
    8588
    8689    Shell::~Shell()
    8790    {
    88         OutputHandler::getOutStream().setOutputBuffer(0);
    89         if (this->inputBuffer_)
    90             this->inputBuffer_->destroy();
     91        OutputHandler::getInstance().unregisterOutputListener(this);
     92        this->inputBuffer_->destroy();
    9193    }
    9294
    9395    void Shell::setConfigValues()
    9496    {
    95         SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
     97        SetConfigValue(maxHistoryLength_, 100)
    9698            .callback(this, &Shell::commandHistoryLengthChanged);
    97         SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
     99        SetConfigValue(historyOffset_, 0)
    98100            .callback(this, &Shell::commandHistoryOffsetChanged);
    99101        SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>());
     102
     103#ifdef ORXONOX_RELEASE
     104        const unsigned int defaultLevel = 1;
     105#else
     106        const unsigned int defaultLevel = 3;
     107#endif
     108        SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevel_, "softDebugLevel" + this->consoleName_, "OutputHandler", defaultLevel)
     109            .description("The maximal level of debug output shown in the Shell");
     110        this->setSoftDebugLevel(this->softDebugLevel_);
    100111    }
    101112
     
    121132    {
    122133        this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
    123         this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
    124         this->inputBuffer_->registerListener(this, &Shell::hintandcomplete, '\t', true);
    125         this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
    126         this->inputBuffer_->registerListener(this, &Shell::deletechar, KeyCode::Delete);
    127         this->inputBuffer_->registerListener(this, &Shell::exit, static_cast<char>(27), true);
    128         this->inputBuffer_->registerListener(this, &Shell::cursor_right, KeyCode::Right);
    129         this->inputBuffer_->registerListener(this, &Shell::cursor_left, KeyCode::Left);
    130         this->inputBuffer_->registerListener(this, &Shell::cursor_end, KeyCode::End);
    131         this->inputBuffer_->registerListener(this, &Shell::cursor_home, KeyCode::Home);
    132         this->inputBuffer_->registerListener(this, &Shell::history_up, KeyCode::Up);
    133         this->inputBuffer_->registerListener(this, &Shell::history_down, KeyCode::Down);
    134         this->inputBuffer_->registerListener(this, &Shell::scroll_up, KeyCode::PageUp);
    135         this->inputBuffer_->registerListener(this, &Shell::scroll_down, KeyCode::PageDown);
    136     }
    137 
    138     void Shell::clearShell()
    139     {
    140         Shell::getInstance().clearLines();
    141     }
    142 
     134        this->inputBuffer_->registerListener(this, &Shell::execute,         '\r',   false);
     135        this->inputBuffer_->registerListener(this, &Shell::execute,         '\n',   false);
     136        this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t',   true);
     137        this->inputBuffer_->registerListener(this, &Shell::backspace,       '\b',   true);
     138        this->inputBuffer_->registerListener(this, &Shell::backspace,       '\177', true);
     139        this->inputBuffer_->registerListener(this, &Shell::exit,            '\033', true); // escape
     140        this->inputBuffer_->registerListener(this, &Shell::deleteChar,      KeyCode::Delete);
     141        this->inputBuffer_->registerListener(this, &Shell::cursorRight,     KeyCode::Right);
     142        this->inputBuffer_->registerListener(this, &Shell::cursorLeft,      KeyCode::Left);
     143        this->inputBuffer_->registerListener(this, &Shell::cursorEnd,       KeyCode::End);
     144        this->inputBuffer_->registerListener(this, &Shell::cursorHome,      KeyCode::Home);
     145        this->inputBuffer_->registerListener(this, &Shell::historyUp,       KeyCode::Up);
     146        this->inputBuffer_->registerListener(this, &Shell::historyDown,     KeyCode::Down);
     147        if (this->bScrollable_)
     148        {
     149            this->inputBuffer_->registerListener(this, &Shell::scrollUp,    KeyCode::PageUp);
     150            this->inputBuffer_->registerListener(this, &Shell::scrollDown,  KeyCode::PageDown);
     151        }
     152        else
     153        {
     154            this->inputBuffer_->registerListener(this, &Shell::historySearchUp,   KeyCode::PageUp);
     155            this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown);
     156        }
     157    }
     158
     159    /*
    143160    void Shell::history()
    144161    {
     
    146163
    147164        for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i)
    148             instance.addLine(instance.commandHistory_[i], -1);
     165            instance.addOutputLine(instance.commandHistory_[i], -1);
    149166        for (unsigned int i =  0; i < instance.historyOffset_; ++i)
    150             instance.addLine(instance.commandHistory_[i], -1);
    151     }
     167            instance.addOutputLine(instance.commandHistory_[i], -1);
     168    }
     169    */
    152170
    153171    void Shell::registerListener(ShellListener* listener)
    154172    {
    155         this->listeners_.insert(this->listeners_.end(), listener);
     173        this->listeners_.push_back(listener);
    156174    }
    157175
     
    161179        {
    162180            if ((*it) == listener)
    163                 this->listeners_.erase(it++);
     181                it = this->listeners_.erase(it);
    164182            else
    165183                ++it;
     
    170188    {
    171189        this->inputBuffer_->setCursorPosition(cursor);
    172         SHELL_UPDATE_LISTENERS(cursorChanged);
    173     }
    174 
    175     void Shell::setInput(const std::string& input)
    176     {
    177         this->inputBuffer_->set(input);
    178         this->inputChanged();
    179     }
    180 
    181     void Shell::addLine(const std::string& line, int level)
    182     {
    183         int original_level = OutputHandler::getOutStream().getOutputLevel();
    184         OutputHandler::getOutStream().setOutputLevel(level);
    185 
    186         if (!this->finishedLastLine_)
    187             this->outputBuffer_ << std::endl;
    188 
    189         this->outputBuffer_ << line << std::endl;
    190         OutputHandler::getOutStream().setOutputLevel(original_level);
    191     }
    192 
    193     void Shell::clearLines()
    194     {
    195         this->lines_.clear();
    196         this->scrollIterator_ = this->lines_.begin();
     190        this->updateListeners<&ShellListener::cursorChanged>();
     191    }
     192
     193    void Shell::addOutputLine(const std::string& line, int level)
     194    {
     195        // Make sure we really only have one line per line (no new lines!)
     196        SubString lines(line, '\n');
     197        for (unsigned i = 0; i < lines.size(); ++i)
     198        {
     199            if (level <= this->softDebugLevel_)
     200                this->outputLines_.push_front(lines[i]);
     201            this->updateListeners<&ShellListener::lineAdded>();
     202        }
     203    }
     204
     205    void Shell::clearOutput()
     206    {
     207        this->outputLines_.clear();
     208        this->scrollIterator_ = this->outputLines_.begin();
    197209
    198210        this->scrollPosition_ = 0;
    199         this->finishedLastLine_ = true;
    200 
    201         SHELL_UPDATE_LISTENERS(linesChanged);
     211        this->bFinishedLastLine_ = true;
     212
     213        this->updateListeners<&ShellListener::linesChanged>();
    202214    }
    203215
     
    207219            return this->scrollIterator_;
    208220        else
    209             return this->lines_.begin();
     221            return this->outputLines_.begin();
    210222    }
    211223
    212224    std::list<std::string>::const_iterator Shell::getEndIterator() const
    213225    {
    214         return this->lines_.end();
     226        return this->outputLines_.end();
    215227    }
    216228
     
    231243    }
    232244
    233     void Shell::outputChanged()
    234     {
    235         std::string output;
    236         bool newline;
     245    void Shell::outputChanged(int level)
     246    {
     247        bool newline = false;
    237248        do
    238249        {
    239             newline = this->outputBuffer_.getLine(&output);
     250            std::string output;
     251            std::getline(this->outputBuffer_, output);
     252
     253            bool eof = this->outputBuffer_.eof();
     254            bool fail = this->outputBuffer_.fail();
     255            if (eof)
     256                this->outputBuffer_.flush();
     257            if (eof || fail)
     258                this->outputBuffer_.clear();
     259            newline = (!eof && !fail);
    240260
    241261            if (!newline && output == "")
    242262                break;
    243263
    244             if (this->finishedLastLine_)
     264            if (this->bFinishedLastLine_)
    245265            {
    246                 if (this->bAddOutputLevel_)
    247                     output.insert(0, 1, static_cast<char>(OutputHandler::getOutStream().getOutputLevel()));
    248 
    249                 this->lines_.insert(this->lines_.begin(), output);
     266                if (this->bPrependOutputLevel_)
     267                    output.insert(0, 1, static_cast<char>(level));
     268
     269                this->outputLines_.push_front(output);
    250270
    251271                if (this->scrollPosition_)
    252272                    this->scrollPosition_++;
    253273                else
    254                     this->scrollIterator_ = this->lines_.begin();
    255 
    256                 this->finishedLastLine_ = newline;
     274                    this->scrollIterator_ = this->outputLines_.begin();
     275
     276                this->bFinishedLastLine_ = newline;
    257277
    258278                if (!this->scrollPosition_)
    259279                {
    260                     SHELL_UPDATE_LISTENERS(lineAdded);
     280                    this->updateListeners<&ShellListener::lineAdded>();
    261281                }
    262282            }
    263283            else
    264284            {
    265                 (*this->lines_.begin()) += output;
    266                 this->finishedLastLine_ = newline;
    267                 SHELL_UPDATE_LISTENERS(onlyLastLineChanged);
     285                (*this->outputLines_.begin()) += output;
     286                this->bFinishedLastLine_ = newline;
     287                this->updateListeners<&ShellListener::onlyLastLineChanged>();
    268288            }
    269289
     
    271291    }
    272292
    273     void Shell::inputChanged()
    274     {
    275         SHELL_UPDATE_LISTENERS(inputChanged);
    276         SHELL_UPDATE_LISTENERS(cursorChanged);
    277     }
    278 
    279     void Shell::execute()
    280     {
    281         this->addToHistory(this->inputBuffer_->get());
    282         this->addLine(this->inputBuffer_->get(), 0);
    283 
    284         if (!CommandExecutor::execute(this->inputBuffer_->get()))
    285             this->addLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1);
    286 
    287         this->clear();
    288     }
    289 
    290     void Shell::hintandcomplete()
    291     {
    292         this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
    293         this->addLine(CommandExecutor::hint(this->inputBuffer_->get()), -1);
    294 
    295         this->inputChanged();
    296     }
    297 
    298     void Shell::backspace()
    299     {
    300         this->inputBuffer_->removeBehindCursor();
    301         SHELL_UPDATE_LISTENERS(inputChanged);
    302         SHELL_UPDATE_LISTENERS(cursorChanged);
    303     }
    304 
    305     void Shell::deletechar()
    306     {
    307         this->inputBuffer_->removeAtCursor();
    308         SHELL_UPDATE_LISTENERS(inputChanged);
    309     }
    310 
    311     void Shell::clear()
     293    void Shell::clearInput()
    312294    {
    313295        this->inputBuffer_->clear();
    314296        this->historyPosition_ = 0;
    315         SHELL_UPDATE_LISTENERS(inputChanged);
    316         SHELL_UPDATE_LISTENERS(cursorChanged);
    317     }
    318 
    319     void Shell::cursor_right()
     297        this->updateListeners<&ShellListener::inputChanged>();
     298        this->updateListeners<&ShellListener::cursorChanged>();
     299    }
     300
     301    void Shell::setPromptPrefix(const std::string& str)
     302    {
     303    }
     304
     305
     306    // ##########################################
     307    // ###   InputBuffer callback functions   ###
     308    // ##########################################
     309
     310    void Shell::inputChanged()
     311    {
     312        this->updateListeners<&ShellListener::inputChanged>();
     313        this->updateListeners<&ShellListener::cursorChanged>();
     314    }
     315
     316    void Shell::execute()
     317    {
     318        this->addToHistory(this->inputBuffer_->get());
     319        this->updateListeners<&ShellListener::executed>();
     320
     321        if (!CommandExecutor::execute(this->inputBuffer_->get()))
     322            this->addOutputLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1);
     323
     324        this->clearInput();
     325    }
     326
     327    void Shell::hintAndComplete()
     328    {
     329        this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
     330        this->addOutputLine(CommandExecutor::hint(this->inputBuffer_->get()), -1);
     331
     332        this->inputChanged();
     333    }
     334
     335    void Shell::backspace()
     336    {
     337        this->inputBuffer_->removeBehindCursor();
     338        this->updateListeners<&ShellListener::inputChanged>();
     339        this->updateListeners<&ShellListener::cursorChanged>();
     340    }
     341
     342    void Shell::exit()
     343    {
     344        if (this->inputBuffer_->getSize() > 0)
     345        {
     346            this->clearInput();
     347            return;
     348        }
     349
     350        this->clearInput();
     351        this->scrollPosition_ = 0;
     352        this->scrollIterator_ = this->outputLines_.begin();
     353
     354        this->updateListeners<&ShellListener::exit>();
     355    }
     356
     357    void Shell::deleteChar()
     358    {
     359        this->inputBuffer_->removeAtCursor();
     360        this->updateListeners<&ShellListener::inputChanged>();
     361    }
     362
     363    void Shell::cursorRight()
    320364    {
    321365        this->inputBuffer_->increaseCursor();
    322         SHELL_UPDATE_LISTENERS(cursorChanged);
    323     }
    324 
    325     void Shell::cursor_left()
     366        this->updateListeners<&ShellListener::cursorChanged>();
     367    }
     368
     369    void Shell::cursorLeft()
    326370    {
    327371        this->inputBuffer_->decreaseCursor();
    328         SHELL_UPDATE_LISTENERS(cursorChanged);
    329     }
    330 
    331     void Shell::cursor_end()
     372        this->updateListeners<&ShellListener::cursorChanged>();
     373    }
     374
     375    void Shell::cursorEnd()
    332376    {
    333377        this->inputBuffer_->setCursorToEnd();
    334         SHELL_UPDATE_LISTENERS(cursorChanged);
    335     }
    336 
    337     void Shell::cursor_home()
     378        this->updateListeners<&ShellListener::cursorChanged>();
     379    }
     380
     381    void Shell::cursorHome()
    338382    {
    339383        this->inputBuffer_->setCursorToBegin();
    340         SHELL_UPDATE_LISTENERS(cursorChanged);
    341     }
    342 
    343     void Shell::history_up()
     384        this->updateListeners<&ShellListener::cursorChanged>();
     385    }
     386
     387    void Shell::historyUp()
    344388    {
    345389        if (this->historyPosition_ < this->commandHistory_.size())
     
    350394    }
    351395
    352     void Shell::history_down()
     396    void Shell::historyDown()
    353397    {
    354398        if (this->historyPosition_ > 0)
     
    359403    }
    360404
    361     void Shell::scroll_up()
    362     {
    363         if (this->scrollIterator_ != this->lines_.end())
     405    void Shell::historySearchUp()
     406    {
     407        if (this->historyPosition_ == this->historyOffset_)
     408            return;
     409        unsigned int cursorPosition = this->getCursorPosition();
     410        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position
     411        for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
     412        {
     413            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
     414            {
     415                this->historyPosition_ = newPos;
     416                this->inputBuffer_->set(this->getFromHistory());
     417                this->setCursorPosition(cursorPosition);
     418                return;
     419            }
     420        }
     421    }
     422
     423    void Shell::historySearchDown()
     424    {
     425        if (this->historyPosition_ == 0)
     426            return;
     427        unsigned int cursorPosition = this->getCursorPosition();
     428        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning
     429        for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
     430        {
     431            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
     432            {
     433                this->historyPosition_ = newPos;
     434                this->inputBuffer_->set(this->getFromHistory());
     435                this->setCursorPosition(cursorPosition);
     436                return;
     437            }
     438        }
     439    }
     440
     441    void Shell::scrollUp()
     442    {
     443        if (this->scrollIterator_ != this->outputLines_.end())
    364444        {
    365445            ++this->scrollIterator_;
    366446            ++this->scrollPosition_;
    367447
    368             SHELL_UPDATE_LISTENERS(linesChanged);
    369         }
    370     }
    371 
    372     void Shell::scroll_down()
    373     {
    374         if (this->scrollIterator_ != this->lines_.begin())
     448            this->updateListeners<&ShellListener::linesChanged>();
     449        }
     450    }
     451
     452    void Shell::scrollDown()
     453    {
     454        if (this->scrollIterator_ != this->outputLines_.begin())
    375455        {
    376456            --this->scrollIterator_;
    377457            --this->scrollPosition_;
    378458
    379             SHELL_UPDATE_LISTENERS(linesChanged);
    380         }
    381     }
    382 
    383     void Shell::exit()
    384     {
    385         if (this->inputBuffer_->getSize() > 0)
    386         {
    387             this->clear();
    388             return;
    389         }
    390 
    391         this->clear();
    392         this->scrollPosition_ = 0;
    393         this->scrollIterator_ = this->lines_.begin();
    394 
    395         SHELL_UPDATE_LISTENERS(exit);
     459            this->updateListeners<&ShellListener::linesChanged>();
     460        }
    396461    }
    397462}
  • code/trunk/src/libraries/core/Shell.h

    r5781 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
     
    3232#include "CorePrereqs.h"
    3333
    34 #include <cassert>
    3534#include <list>
     35#include <sstream>
    3636#include <string>
    3737#include <vector>
    3838
    39 #include "util/OutputBuffer.h"
    40 #include "input/InputBuffer.h"
     39#include "util/OutputHandler.h"
    4140#include "OrxonoxClass.h"
    4241#include "ConfigFileManager.h"
     42#include "input/InputBuffer.h"
    4343
    4444namespace orxonox
     
    5757            virtual void inputChanged() {}
    5858            virtual void cursorChanged() {}
     59            virtual void executed() {}
    5960            virtual void exit() {}
    6061    };
    6162
    62     class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputBufferListener
     63
     64    class _CoreExport Shell : virtual public OrxonoxClass, public OutputListener
    6365    {
    64         friend class Singleton<Shell>;
    6566        public:
    66             Shell();
    67             virtual ~Shell();
     67            Shell(const std::string& consoleName, bool bScrollable, bool bPrependOutputLevel = false);
     68            ~Shell();
    6869
    69             static void clearShell();
    70             static void history();
    71 
    72             virtual void setConfigValues();
     70            void setConfigValues();
    7371            void commandHistoryOffsetChanged();
    7472            void commandHistoryLengthChanged();
     
    7977            inline InputBuffer* getInputBuffer()
    8078                { return this->inputBuffer_; }
    81             inline OutputBuffer& getOutputBuffer()
    82                 { return this->outputBuffer_; }
    8379
    8480            void setCursorPosition(unsigned int cursor);
     
    8682                { return this->inputBuffer_->getCursorPosition(); }
    8783
    88             void setInput(const std::string& input);
    89 
    90             inline void clearInput()
    91                 { this->setInput(""); }
    9284            inline std::string getInput() const
    9385                { return this->inputBuffer_->get(); }
     
    9688            std::list<std::string>::const_iterator getEndIterator() const;
    9789
    98             void addLine(const std::string& line, int level = 0);
    99             void clearLines();
     90            void addOutputLine(const std::string& line, int level = 0);
     91            void clearOutput();
    10092
    10193            inline unsigned int getNumLines() const
    102                 { return this->lines_.size(); }
     94                { return this->outputLines_.size(); }
    10395            inline unsigned int getScrollPosition() const
    10496                { return this->scrollPosition_; }
    10597
    106             inline void addOutputLevel(bool bAddOutputLevel)
    107                 { this->bAddOutputLevel_ = bAddOutputLevel; }
     98            inline const std::string& getPromptPrefix() const { return this->promptPrefix_; }
     99            void setPromptPrefix(const std::string& str);
    108100
    109101        private:
    110102            Shell(const Shell& other);
    111103
     104            void addToHistory(const std::string& command);
     105            std::string getFromHistory() const;
     106            void clearInput();
     107            // OutputListener
     108            void outputChanged(int level);
     109
    112110            void configureInputBuffer();
    113111
    114             void addToHistory(const std::string& command);
    115             std::string getFromHistory() const;
    116 
    117             virtual void outputChanged();
     112            // InputBuffer callbacks
    118113            void inputChanged();
    119114            void execute();
    120             void hintandcomplete();
     115            void hintAndComplete();
    121116            void backspace();
    122             void deletechar();
    123             void clear();
    124             void cursor_right();
    125             void cursor_left();
    126             void cursor_end();
    127             void cursor_home();
    128             void history_up();
    129             void history_down();
    130             void scroll_up();
    131             void scroll_down();
     117            void deleteChar();
     118            void cursorRight();
     119            void cursorLeft();
     120            void cursorEnd();
     121            void cursorHome();
     122            void historyUp();
     123            void historyDown();
     124            void historySearchUp();
     125            void historySearchDown();
     126            void scrollUp();
     127            void scrollDown();
    132128            void exit();
    133129
     130            template <void (ShellListener::*F)()>
     131            void updateListeners()
     132            {
     133                for (std::list<ShellListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
     134                    ((*(it++))->*F)();
     135            }
     136
    134137            std::list<ShellListener*> listeners_;
    135             InputBuffer* inputBuffer_;
    136             OutputBuffer outputBuffer_;
    137             bool finishedLastLine_;
    138             std::list<std::string> lines_;
     138            InputBuffer*              inputBuffer_;
     139            std::stringstream        outputBuffer_;
     140            bool                      bFinishedLastLine_;
     141            std::list<std::string>    outputLines_;
    139142            std::list<std::string>::const_iterator scrollIterator_;
    140             unsigned int scrollPosition_;
    141             std::vector<std::string> commandHistory_;
    142             unsigned int maxHistoryLength_;
    143             unsigned int historyPosition_;
    144             unsigned int historyOffset_;
    145             bool bAddOutputLevel_;
     143            unsigned int              scrollPosition_;
     144            unsigned int              historyPosition_;
     145            ConfigFileType            commandHistoryConfigFileType_;
    146146
    147             ConfigFileType commandHistoryConfigFileType_;
     147            std::string               promptPrefix_;
     148            const std::string         consoleName_;
     149            const bool                bPrependOutputLevel_;
     150            const bool                bScrollable_;
    148151
    149             static Shell* singletonPtr_s;
     152            // Config values
     153            unsigned int              maxHistoryLength_;
     154            unsigned int              historyOffset_;
     155            std::vector<std::string>  commandHistory_;
     156            int                       softDebugLevel_;
    150157    };
    151158}
  • code/trunk/src/libraries/core/input/InputBuffer.cc

    r5781 r6105  
    8080    void InputBuffer::setConfigValues()
    8181    {
    82         SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat deleay of the input buffer");
     82        SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat delay of the input buffer");
    8383        SetConfigValue(keyRepeatTime_, 0.022).description("Key repeat time of the input buffer");
    8484
     
    186186    void InputBuffer::processKey(const KeyEvent& evt)
    187187    {
     188        // Prevent disaster when switching applications
    188189        if (evt.isModifierDown(KeyboardModifier::Alt) && evt.getKeyCode() == KeyCode::Tab)
    189190            return;
     
    222223
    223224    /**
    224         @brief This update() function is called by the InputManager if the InputBuffer is active.
     225        @brief This update() function is called by the InputState if the InputBuffer is active.
    225226        @param dt Delta time
    226227    */
  • code/trunk/src/libraries/core/input/InputBuffer.h

    r5781 r6105  
    162162                { if (this->cursor_ > 0) { --this->cursor_; } }
    163163
     164            void buttonPressed(const KeyEvent& evt);
     165
    164166        private:
    165167            bool charIsAllowed(const char& input);
    166168
    167             void buttonPressed(const KeyEvent& evt);
    168169            void buttonHeld   (const KeyEvent& evt);
    169170            void processKey   (const KeyEvent& evt);
  • code/trunk/src/libraries/core/input/InputHandler.h

    r5781 r6105  
    7373            , modifiers_(0)
    7474        { }
     75        KeyEvent(KeyCode::ByEnum key, unsigned int text, int modifiers)
     76            : key_(key)
     77            , text_(text)
     78            , modifiers_(modifiers)
     79        { }
    7580        bool operator==(const KeyEvent& rhs) const
    7681            { return rhs.key_ == key_; }
     
    97102
    98103        Derive from this class if you wish to receive input events.
    99         But keep in mind that this is pointless wihtout first having an InputState.
     104        But keep in mind that this is pointless without first having an InputState.
    100105    @note
    101106        The definitions for the button events with the weird arguments are simply
    102         to avoid redunant code in the input devices.
     107        to avoid redundant code in the input devices.
    103108    */
    104109    class _CoreExport InputHandler
  • code/trunk/src/libraries/core/input/InputManager.cc

    r6021 r6105  
    190190            // Exception-safety
    191191            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
    192             CCOUT(ORX_DEBUG) << "Created OIS input manager." << std::endl;
     192            CCOUT(4) << "Created OIS input manager." << std::endl;
    193193
    194194            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
     
    232232        }
    233233        else
    234             CCOUT(ORX_WARNING) << "Warning: No mouse found! Proceeding without mouse support." << std::endl;
     234            CCOUT(2) << "Warning: No mouse found! Proceeding without mouse support." << std::endl;
    235235    }
    236236
  • code/trunk/src/libraries/network/packet/Packet.cc

    r5781 r6105  
    230230*/
    231231void Packet::deletePacket(ENetPacket *enetPacket){
    232   // Get our Packet from a gloabal map with all Packets created in the send() method of Packet.
     232  // Get our Packet from a global map with all Packets created in the send() method of Packet.
    233233  std::map<size_t, Packet*>::iterator it = packetMap_.find(reinterpret_cast<size_t>(enetPacket));
    234234  assert(it != packetMap_.end());
  • code/trunk/src/libraries/tools/ResourceCollection.h

    r5781 r6105  
    3838namespace orxonox
    3939{
    40     class ResourceLocation;
    41 
    4240    class _ToolsExport ResourceCollection : public BaseObject
    4341    {
  • code/trunk/src/libraries/util/CMakeLists.txt

    r5929 r6105  
    2929  CRC32.cc
    3030  ExprParser.cc
    31   OutputBuffer.cc
    3231  OutputHandler.cc
    3332  SignalHandler.cc
  • code/trunk/src/libraries/util/Debug.h

    r5738 r6105  
    2121 *
    2222 *   Author:
    23  *      Benjamin Grauer
     23 *      Fabian 'x3n' Landau
     24 *      Reto Grieder
    2425 *   Co-authors:
    25  *      Fabian 'x3n' Landau
     26 *      ...
    2627 *
    2728 */
    2829
    2930/**
    30     @file
    31     @brief Handles different output-levels of errors, warnings, infos and debug information.
     31@file
     32@brief
     33    Handles different output-levels of errors, warnings, infos and debug information.
    3234
    3335    The COUT(level) macro acts like std::cout, but the output is only performed if the given
     
    3537
    3638    There are two used values in this file:
    37      - The hard debug level is used during compiletime. It describes the highest allowed output level.
     39     - The hard debug level is used during compile time. It describes the highest allowed output level.
    3840     - The soft debug level is used during runtime and is the maximum of the three configurable
    39        output-levels for console, logfile and ingame shell.
     41       output-levels for console, log file and in game shell.
    4042
    4143    The separation between the three devices is done by the OutputHandler.
     
    5052     6: Crazy debug information
    5153
    52     @example
     54@example
    5355    COUT(0) << "Very important output" << std::endl;
    5456    COUT(1) << "Error: Something went wrong!" << std::endl;
    5557    COUT(2) << "Warning: There might be a problem." << std::endl;
    56     COUT(3) << "Info: It's monday" << std::endl;
     58    COUT(3) << "Info: It's Monday" << std::endl;
    5759    COUT(4) << "Debug: x is 1.23456" << std::endl;
    58  */
     60*/
    5961
    60 #ifndef _Debug_H__
    61 #define _Debug_H__
     62#ifndef _Util_Debug_H__
     63#define _Util_Debug_H__
    6264
    6365#include "UtilPrereqs.h"
    64 
    6566#include "OutputHandler.h"
    6667
    6768namespace orxonox
    6869{
    69     /**
    70         @brief Returns the soft debug level, stored in the only existing instance of the OutputHandler class, configured in the config-file.
    71         @return The soft debug level
    72     */
    73     inline int getSoftDebugLevel()
    74     {
    75         return OutputHandler::getSoftDebugLevel();
    76     }
     70    // Just for convenience
     71    using std::endl;
    7772
    78     using std::endl;
     73    //! Adjust to discard certain output with level > hardDebugLevel at compile time
     74    const int hardDebugLevel = OutputLevel::Verbose;
    7975}
    8076
    81 // DEFINE ERROR MODES
    82 #define ORX_NONE            0
    83 #define ORX_ERROR           1
    84 #define ORX_WARNING         2
    85 #define ORX_INFO            3
    86 #define ORX_DEBUG           4
    87 #define ORX_VERBOSE         5
    88 #define ORX_ULTRA           6
     77/**
     78@brief
     79    Logs text output: use exactly like std::cout, but specify an output
     80    level as argument.
     81@example
     82    COUT(3) << "Some info" << std::endl;
     83@note
     84    The ? : operator requires both possible results to have the type of
     85    the first. This is achieved by the int conversion operator dummy
     86    in the OutputHandler.
     87*/
     88#define COUT(level)                                                    \
     89    /*if*/ (level > orxonox::hardDebugLevel) ?                         \
     90        0                                                              \
     91    /*else*/ :                                                         \
     92        /*if*/ (level > orxonox::OutputHandler::getSoftDebugLevel()) ? \
     93            0                                                          \
     94        /*else*/ :                                                     \
     95            orxonox::OutputHandler::getOutStream(level)
    8996
    90 //definitions
    91 #define ORX_PRINT_DEBUG_OUTPUT 1
    92 #define ORX_HARD_DEBUG_LEVEL ORX_VERBOSE
    93 
    94 #define COUT_EXEC(x) orxonox::OutputHandler::getOutStream().setOutputLevel(x)
    95 
    96 ////////////////////////////////////////////////////////
    97 ///  COUT: just prints output as is with std::cout   ///
    98 ////////////////////////////////////////////////////////
    99 #define COUTORX_NONE    COUT0
    100 #define COUTORX_ERROR   COUT1
    101 #define COUTORX_WARNING COUT2
    102 #define COUTORX_INFO    COUT3
    103 #define COUTORX_DEBUG   COUT4
    104 #define COUTORX_VERBOSE COUT5
    105 #define COUTORX_ULTRA   COUT6
    106 
    107 #ifndef COUT
    108  #if ORX_PRINT_DEBUG_OUTPUT
    109   #define COUT(x) \
    110    COUT ## x
    111 
    112   #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
    113    #define COUT0 \
    114    (orxonox::getSoftDebugLevel() < ORX_NONE) ? COUT_EXEC(0) : COUT_EXEC(0)
    115   #else
    116    #define COUT0 \
    117     false ? COUT_EXEC(0) : COUT_EXEC(0)
    118   #endif
    119 
    120   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    121    #define COUT1 \
    122     (orxonox::getSoftDebugLevel() < ORX_ERROR) ? COUT_EXEC(1) : COUT_EXEC(1)
    123   #else
    124    #define COUT1 \
    125     false ? COUT_EXEC(1) : COUT_EXEC(1)
    126   #endif
    127 
    128   #if ORX_HARD_DEBUG_LEVEL >= ORX_WARNING
    129    #define COUT2 \
    130     (orxonox::getSoftDebugLevel() < ORX_WARNING) ? COUT_EXEC(2) : COUT_EXEC(2)
    131   #else
    132    #define COUT2 \
    133     false ? COUT_EXEC(2) : COUT_EXEC(2)
    134   #endif
    135 
    136   #if ORX_HARD_DEBUG_LEVEL >= ORX_INFO
    137    #define COUT3 \
    138     (orxonox::getSoftDebugLevel() < ORX_INFO) ? COUT_EXEC(3) : COUT_EXEC(3)
    139   #else
    140    #define COUT3 \
    141     false ? COUT_EXEC(3) : COUT_EXEC(3)
    142   #endif
    143 
    144   #if ORX_HARD_DEBUG_LEVEL >= ORX_DEBUG
    145    #define COUT4 \
    146     (orxonox::getSoftDebugLevel() < ORX_DEBUG) ? COUT_EXEC(4) : COUT_EXEC(4)
    147   #else
    148    #define COUT4 \
    149     false ? COUT_EXEC(4) : COUT_EXEC(4)
    150   #endif
    151 
    152   #if ORX_HARD_DEBUG_LEVEL >= ORX_VERBOSE
    153    #define COUT5 \
    154     (orxonox::getSoftDebugLevel() < ORX_VERBOSE) ? COUT_EXEC(5) : COUT_EXEC(5)
    155   #else
    156    #define COUT5 \
    157     false ? COUT_EXEC(5) : COUT_EXEC(5)
    158   #endif
    159 
    160   #if ORX_HARD_DEBUG_LEVEL >= ORX_ULTRA
    161    #define COUT6 \
    162     (orxonox::getSoftDebugLevel() < ORX_ULTRA) ? COUT_EXEC(6) : COUT_EXEC(6)
    163   #else
    164    #define COUT6 \
    165     false ? COUT_EXEC(6) : COUT_EXEC(6)
    166   #endif
    167 
    168  #else /* if ORX_PRINT_DEBUG_OUTPUT */
    169   #define COUT(x) \
    170     false ? COUT_EXEC(6) : COUT_EXEC(6)
    171  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
    172 
    173 #endif /* ifndef COUT */
    174 
    175 
    176 /////////////////////////////////////////////////////////////////////
    177 ///  CCOUT: Prints output with std::cout and adds the classname   ///
    178 /////////////////////////////////////////////////////////////////////
    179 #define CCOUTORX_NONE    CCOUT0
    180 #define CCOUTORX_ERROR   CCOUT1
    181 #define CCOUTORX_WARNING CCOUT2
    182 #define CCOUTORX_INFO    CCOUT3
    183 #define CCOUTORX_DEBUG   CCOUT4
    184 #define CCOUTORX_VERBOSE CCOUT5
    185 #define CCOUTORX_ULTRA   CCOUT6
    186 
    187 #define CCOUT_EXEC(x) \
    188   orxonox::OutputHandler::getOutStream().setOutputLevel(x) \
    189   << this->getIdentifier()->getName() << ": "
    190 
    191 #ifndef CCOUT
    192  #if ORX_PRINT_DEBUG_OUTPUT
    193   #define CCOUT(x) \
    194    CCOUT ## x
    195 
    196   #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
    197    #define CCOUT0 \
    198     (orxonox::getSoftDebugLevel() < ORX_NONE) ? COUT_EXEC(0) : CCOUT_EXEC(0)
    199   #else
    200    #define CCOUT0 \
    201     false ? COUT_EXEC(0) : CCOUT_EXEC(0)
    202   #endif
    203 
    204   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    205    #define CCOUT1 \
    206     (orxonox::getSoftDebugLevel() < ORX_ERROR) ? COUT_EXEC(1) : CCOUT_EXEC(1)
    207   #else
    208    #define CCOUT1 \
    209     false ? COUT_EXEC(1) : CCOUT_EXEC(1)
    210   #endif
    211 
    212   #if ORX_HARD_DEBUG_LEVEL >= ORX_WARNING
    213    #define CCOUT2 \
    214     (orxonox::getSoftDebugLevel() < ORX_WARNING) ? COUT_EXEC(2) : CCOUT_EXEC(2)
    215   #else
    216    #define CCOUT2 \
    217     false ? COUT_EXEC(2) : CCOUT_EXEC(2)
    218   #endif
    219 
    220   #if ORX_HARD_DEBUG_LEVEL >= ORX_INFO
    221    #define CCOUT3 \
    222     (orxonox::getSoftDebugLevel() < ORX_INFO) ? COUT_EXEC(3) : CCOUT_EXEC(3)
    223   #else
    224    #define CCOUT3 \
    225     false ? COUT_EXEC(3) : CCOUT_EXEC(3)
    226   #endif
    227 
    228   #if ORX_HARD_DEBUG_LEVEL >= ORX_DEBUG
    229    #define CCOUT4 \
    230     (orxonox::getSoftDebugLevel() < ORX_DEBUG) ? COUT_EXEC(4) : CCOUT_EXEC(4)
    231   #else
    232    #define CCOUT4 \
    233     false ? COUT_EXEC(4) : CCOUT_EXEC(4)
    234   #endif
    235 
    236   #if ORX_HARD_DEBUG_LEVEL >= ORX_VERBOSE
    237    #define CCOUT5 \
    238     (orxonox::getSoftDebugLevel() < ORX_VERBOSE) ? COUT_EXEC(5) : CCOUT_EXEC(5)
    239   #else
    240    #define CCOUT5 \
    241     false ? COUT_EXEC(5) : CCOUT_EXEC(5)
    242   #endif
    243 
    244   #if ORX_HARD_DEBUG_LEVEL >= ORX_ULTRA
    245    #define CCOUT6 \
    246     (orxonox::getSoftDebugLevel() < ORX_ULTRA) ? COUT_EXEC(6) : CCOUT_EXEC(6)
    247   #else
    248    #define CCOUT6 \
    249     false ? COUT_EXEC(6) : CCOUT_EXEC(6)
    250   #endif
    251 
    252  #else /* if ORX_PRINT_DEBUG_OUTPUT */
    253   #define CCOUT(x) \
    254    false ? CCOUT_EXEC(6) : CCOUT_EXEC(6)
    255  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
    256 
    257 #endif /* ifndef CCOUT */
    258 
    259 #endif /* _Debug_H__ */
     97#endif /* _Util_Debug_H__ */
  • code/trunk/src/libraries/util/OrxAssert.h

    r5738 r6105  
    4444#ifndef NDEBUG
    4545#define OrxAssert(Assertion, ErrorMessage) \
    46     Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream().setOutputLevel(1) << ErrorMessage << std::endl); \
     46    Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream(1) << ErrorMessage << std::endl); \
    4747    assert(Assertion)
    4848#else
  • code/trunk/src/libraries/util/OutputHandler.cc

    r5738 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Implementation of the OutputHandler class.
     30@file
     31@brief
     32    Definition of classes related to output (logging).
    3233*/
    3334
    3435#include "OutputHandler.h"
    3536
     37#include <algorithm>
    3638#include <ctime>
    3739#include <cstdlib>
     40#include <fstream>
     41#include <sstream>
     42
     43#include "Debug.h"
    3844
    3945namespace orxonox
    4046{
     47    //! How the log file shall be named on the filesystem
     48    const std::string logFileBaseName_g = "orxonox.log";
     49
     50    /////////////////////////
     51    ///// LogFileWriter /////
     52    /////////////////////////
    4153    /**
    42         @brief Constructor: Opens the logfile and writes the first line.
    43         @param logfilename The name of the logfile
     54    @brief
     55        Writes the output to the log file.
     56    @note
     57        As long as the correct log path is not yet known (for pre main code), the
     58        LogFileWriter will write to a temporary file in /temp (Unix) or %TEMP% (Windows).
     59        As soon as you set the correct path setLogPath the content of the temporary file
     60        is read and put into the new file as well.
    4461    */
     62    class LogFileWriter : public OutputListener
     63    {
     64    public:
     65        /**
     66        @brief
     67            Gets temporary log path and starts the log file
     68        @param outputHandler
     69            This is only required to avoid another call to getInstance (this c'tor was
     70            called from getInstance!)
     71        */
     72        LogFileWriter()
     73            : OutputListener(OutputHandler::logFileOutputListenerName_s)
     74        {
     75            // Get path for a temporary file
     76#ifdef ORXONOX_PLATFORM_WINDOWS
     77            char* pTempDir = getenv("TEMP");
     78            this->logFilename_ = std::string(pTempDir) + "/" + logFileBaseName_g;
     79#else
     80            this->logFilename_ = std::string("/tmp/") + logFileBaseName_g;
     81#endif
     82
     83            // Get current time
     84            time_t rawtime;
     85            struct tm* timeinfo;
     86            time(&rawtime);
     87            timeinfo = localtime(&rawtime);
     88
     89            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     90            this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
     91            this->logFile_.flush();
     92
     93            this->outputStream_ = &this->logFile_;
     94        }
     95
     96        //! Closes the log file
     97        ~LogFileWriter()
     98        {
     99            this->logFile_ << "Closed log" << std::endl;
     100            this->logFile_.close();
     101        }
     102
     103        //! Changes the log path
     104        void setLogPath(const std::string& path)
     105        {
     106            this->logFile_.close();
     107            // Read old file into a buffer
     108            std::ifstream old(this->logFilename_.c_str());
     109            this->logFilename_ = path + logFileBaseName_g;
     110            // Open the new file and feed it the content of the old one
     111            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     112            this->logFile_ << old.rdbuf();
     113            this->logFile_.flush();
     114            old.close();
     115        }
     116
     117    private:
     118        std::ofstream logFile_;     //! File handle for the log file
     119        std::string   logFilename_; //! Filename of the log file
     120    };
     121
     122
     123    /////////////////////////
     124    ///// ConsoleWriter /////
     125    /////////////////////////
     126    /**
     127    @brief
     128        Writes the output to std::cout.
     129    @note
     130        This listener will usually be disable once an actual shell with console is instantiated.
     131    */
     132    class ConsoleWriter : public OutputListener
     133    {
     134    public:
     135        //! Only assigns the output stream with std::cout
     136        ConsoleWriter()
     137            : OutputListener("consoleLog")
     138        {
     139            this->outputStream_ = &std::cout;
     140        }
     141    };
     142
     143
     144    ///////////////////////////
     145    ///// MemoryLogWriter /////
     146    ///////////////////////////
     147    /**
     148    @brief
     149        OutputListener that writes all the output piece by piece to an array
     150        associated with the corresponding output level.
     151    @note
     152        Only output below or equal to the current soft debug level is written
     153        to minimise huge arrays for the normal run.
     154    */
     155    class MemoryLogWriter : public OutputListener
     156    {
     157    public:
     158        friend class OutputHandler;
     159
     160        /**
     161        @brief
     162            Sets the right soft debug level and registers itself
     163        @param outputHandler
     164            This is only required to avoid another call to getInstance (this c'tor was
     165            called from getInstance!)
     166        */
     167        MemoryLogWriter()
     168            : OutputListener("memoryLog")
     169        {
     170            this->outputStream_ = &this->buffer_;
     171        }
     172
     173        //! Pushed the just written output to the internal array
     174        void outputChanged(int level)
     175        {
     176            // Read ostringstream and store it
     177            this->output_.push_back(std::make_pair(level, this->buffer_.str()));
     178            // Clear content and flags
     179            this->buffer_.str(std::string());
     180            this->buffer_.clear();
     181        }
     182
     183    private:
     184        std::ostringstream                        buffer_; //! Stream object used to process the output
     185        std::vector<std::pair<int, std::string> > output_; //! Vector containing ALL output
     186    };
     187
     188
     189    /////////////////////////
     190    ///// OutputHandler /////
     191    /////////////////////////
     192    const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
     193          int         OutputHandler::softDebugLevel_s = hardDebugLevel;
     194
     195    //! Creates the LogFileWriter and the MemoryLogWriter
    45196    OutputHandler::OutputHandler()
    46     {
    47 #ifdef ORXONOX_PLATFORM_WINDOWS
    48         char* pTempDir = getenv("TEMP");
    49         this->logfilename_ = std::string(pTempDir) + "/orxonox.log";
     197        : outputLevel_(OutputLevel::Verbose)
     198    {
     199#ifdef ORXONOX_RELEASE
     200        const OutputLevel::Value defaultLevelConsole = OutputLevel::Error;
     201        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Info;
    50202#else
    51         this->logfilename_ = "/tmp/orxonox.log";
     203        const OutputLevel::Value defaultLevelConsole = OutputLevel::Info;
     204        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Debug;
    52205#endif
    53 #ifdef NDEBUG
    54         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 2;
    55         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 1;
    56 #else
    57         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 3;
    58         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 2;
    59 #endif
    60 
    61         this->outputBuffer_ = &this->fallbackBuffer_;
    62         this->logfile_.open(this->logfilename_.c_str(), std::fstream::out);
    63 
    64         time_t rawtime;
    65         struct tm* timeinfo;
    66         time(&rawtime);
    67         timeinfo = localtime(&rawtime);
    68 
    69         this->logfile_ << "Started log on " << asctime(timeinfo) << std::endl;
    70         this->logfile_.flush();
    71     }
    72 
    73     /**
    74         @brief Destructor: Writes the last line to the logfile and closes it.
    75     */
     206
     207        this->logFile_ = new LogFileWriter();
     208        // Use default level until we get the configValue from the Core
     209        this->logFile_->softDebugLevel_ = defaultLevelLogFile;
     210        this->registerOutputListener(this->logFile_);
     211
     212        this->consoleWriter_ = new ConsoleWriter();
     213        this->consoleWriter_->softDebugLevel_ = defaultLevelConsole;
     214        this->registerOutputListener(this->consoleWriter_);
     215
     216        this->output_  = new MemoryLogWriter();
     217        // We capture as much input as the listener with the highest level
     218        this->output_->softDebugLevel_ = getSoftDebugLevel();
     219        this->registerOutputListener(this->output_);
     220    }
     221
     222    //! Destroys the LogFileWriter and the MemoryLogWriter
    76223    OutputHandler::~OutputHandler()
    77224    {
    78         this->logfile_ << "Closed log" << std::endl;
    79         this->logfile_.close();
    80     }
    81 
    82     /**
    83         @brief Returns a reference to the only existing instance of the OutputHandler class.
    84         @return The instance
    85     */
    86     OutputHandler& OutputHandler::getOutStream()
     225        delete this->logFile_;
     226        delete this->output_;
     227    }
     228
     229    OutputHandler& OutputHandler::getInstance()
    87230    {
    88231        static OutputHandler orxout;
     
    90233    }
    91234
    92     /**
    93         @brief Sets the soft debug level for a given output device.
    94         @param device The output device
    95         @param level The debug level
    96     */
    97     void OutputHandler::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    98     {
    99         OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)] = level;
    100     }
    101 
    102     /**
    103         @brief Returns the soft debug level for a given output device.
    104         @param device The output device
    105         @return The debug level
    106     */
    107     int OutputHandler::getSoftDebugLevel(OutputHandler::OutputDevice device)
    108     {
    109         return OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)];
    110     }
    111 
    112     /**
    113         @brief Sets the OutputBuffer, representing the third output stream.
    114         @param buffer The OutputBuffer
    115     */
    116     void OutputHandler::setOutputBuffer(OutputBuffer* buffer)
    117     {
    118         if (buffer == NULL)
    119             this->outputBuffer_ = &this->fallbackBuffer_;
    120         else
    121         {
    122             buffer->getStream() >> this->outputBuffer_->getStream().rdbuf();
    123             this->outputBuffer_ = buffer;
    124         }
    125     }
    126 
    127     /**
    128         @brief Sets the path where to create orxonox.log
    129         @param Path string with trailing slash
    130     */
     235    void OutputHandler::registerOutputListener(OutputListener* listener)
     236    {
     237        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     238        {
     239            if ((*it)->name_ == listener->name_)
     240            {
     241                COUT(2) << "OutputHandler, Warning: Trying to register two listeners with the same name!" << std::endl;
     242                return;
     243            }
     244        }
     245        this->listeners_.push_back(listener);
     246        // Update global soft debug level
     247        this->setSoftDebugLevel(listener->getOutputListenerName(), listener->getSoftDebugLevel());
     248    }
     249
     250    void OutputHandler::unregisterOutputListener(OutputListener* listener)
     251    {
     252        this->listeners_.remove(listener);
     253    }
     254
    131255    void OutputHandler::setLogPath(const std::string& path)
    132256    {
    133         OutputHandler::getOutStream().logfile_.close();
    134         // store old content
    135         std::ifstream old;
    136         old.open(OutputHandler::getOutStream().logfilename_.c_str());
    137         OutputHandler::getOutStream().logfilename_ = path + "orxonox.log";
    138         OutputHandler::getOutStream().logfile_.open(OutputHandler::getOutStream().logfilename_.c_str(), std::fstream::out);
    139         OutputHandler::getOutStream().logfile_ << old.rdbuf();
    140         old.close();
    141         OutputHandler::getOutStream().logfile_.flush();
    142     }
    143 
    144     /**
    145         @brief Overloaded << operator, redirects the output to the console and the logfile.
    146         @param sb The streambuffer that should be shown in the console
    147         @return A reference to the OutputHandler itself
    148     */
    149     OutputHandler& OutputHandler::operator<<(std::streambuf* sb)
    150     {
    151         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    152             std::cout << sb;
    153 
    154         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    155         {
    156             this->logfile_ << sb;
    157             this->logfile_.flush();
    158         }
    159 
    160         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    161             (*this->outputBuffer_) << sb;
    162 
    163         return *this;
    164     }
    165 
    166     /**
    167         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    168         @param manipulator A function, manipulating the outstream.
    169         @return A reference to the OutputHandler itself
    170     */
    171     OutputHandler& OutputHandler::operator<<(std::ostream& (*manipulator)(std::ostream&))
    172     {
    173         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    174             manipulator(std::cout);
    175 
    176         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    177         {
    178             manipulator(this->logfile_);
    179             this->logfile_.flush();
    180         }
    181 
    182         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    183             (*this->outputBuffer_) << manipulator;
    184 
    185         return *this;
    186     }
    187 
    188     /**
    189         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    190         @param manipulator A function, manipulating the outstream.
    191         @return A reference to the OutputHandler itself
    192     */
    193     OutputHandler& OutputHandler::operator<<(std::ios& (*manipulator)(std::ios&))
    194     {
    195         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    196             manipulator(std::cout);
    197 
    198         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    199         {
    200             manipulator(this->logfile_);
    201             this->logfile_.flush();
    202         }
    203 
    204         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    205             (*this->outputBuffer_) << manipulator;
    206 
    207         return *this;
    208     }
    209 
    210     /**
    211         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    212         @param manipulator A function, manipulating the outstream.
    213         @return A reference to the OutputHandler itself
    214     */
    215     OutputHandler& OutputHandler::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
    216     {
    217         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    218             manipulator(std::cout);
    219 
    220         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    221         {
    222             manipulator(this->logfile_);
    223             this->logfile_.flush();
    224         }
    225 
    226         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    227             (*this->outputBuffer_) << manipulator;
    228 
    229         return *this;
     257        this->logFile_->setLogPath(path);
     258    }
     259
     260    void OutputHandler::disableCout()
     261    {
     262        this->unregisterOutputListener(this->consoleWriter_);
     263    }
     264
     265    void OutputHandler::enableCout()
     266    {
     267        this->registerOutputListener(this->consoleWriter_);
     268    }
     269
     270    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
     271    {
     272        return this->output_->output_.begin();
     273    }
     274
     275    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
     276    {
     277        return this->output_->output_.end();
     278    }
     279
     280    int OutputHandler::getSoftDebugLevel(const std::string& name) const
     281    {
     282        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     283        {
     284            if ((*it)->name_ == name)
     285                return (*it)->softDebugLevel_;
     286        }
     287        return -1;
     288    }
     289
     290    void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
     291    {
     292        int globalSoftDebugLevel = -1;
     293        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     294        {
     295            if ((*it)->name_ == name)
     296                (*it)->softDebugLevel_ = level;
     297            if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
     298                globalSoftDebugLevel = (*it)->softDebugLevel_;
     299        }
     300        // Update global soft debug level
     301        OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
    230302    }
    231303}
  • code/trunk/src/libraries/util/OutputHandler.h

    r5738 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Definition of the OutputHandler class.
    32 
    33     The OutputHandler acts like std::cout, but output isn't only shown in the console,
    34     but also written to the logfile and the ingame shell.
     30@file
     31@brief
     32    Declaration of classes related to output (logging).
    3533*/
    3634
     
    4038#include "UtilPrereqs.h"
    4139
    42 #include <iostream>
    43 #include <fstream>
     40#include <list>
     41#include <ostream>
    4442#include <string>
    45 
    46 #include "OutputBuffer.h"
     43#include <vector>
     44#include <utility>
    4745
    4846namespace orxonox
    4947{
    50     //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
     48    /**
     49    @brief
     50        Denotes different levels of text output (log output)
     51
     52        0, None   : Very important output
     53        1, Error  : Errors
     54        2, Warning: Warnings
     55        3, Info   : Information
     56        4, Debug  : Debug information
     57        5, Verbose: More debug information
     58        6, Ultra  : Crazy debug information
     59    */
     60    namespace OutputLevel
     61    {
     62        enum Value
     63        {
     64            None    = 0,
     65            Error   = 1,
     66            Warning = 2,
     67            Info    = 3,
     68            Debug   = 4,
     69            Verbose = 5,
     70            Ultra   = 6,
     71        };
     72    }
     73
     74    // Forward declarations for classes in the source file
     75    class LogFileWriter;
     76    class ConsoleWriter;
     77    class MemoryLogWriter;
     78
     79    /**
     80    @brief
     81        The OutputHandler acts like std::cout, but output isn't only shown in the console.
     82
     83        You can register your own listener for output by inheriting from OutputListner.
     84        And if you need the output previously processed, iterate over it with
     85        OutputHandler::getOutputVector[Begin/End].
     86        The way to output text is to first set the desired output level with
     87        OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
     88    */
    5189    class _UtilExport OutputHandler
    5290    {
    5391        public:
    54             enum OutputDevice
    55             {
    56                 LD_All = 0,
    57                 LD_Console = 1,
    58                 LD_Logfile = 2,
    59                 LD_Shell = 3
    60             };
    61 
    62             static OutputHandler& getOutStream();
    63 
    64             /** @brief Puts some text on the outstream. @param text The text */
     92            //! Returns a reference to the only existing instance of the OutputHandler class.
     93            static OutputHandler& getInstance();
     94
     95            //! Sets the output level and returns a stream to be used with "<<"
     96            static inline OutputHandler& getOutStream(int level)
     97                { return OutputHandler::getInstance().setOutputLevel(level); }
     98
     99            typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
     100            //! Returns an iterator to the beginning of the all-output vector
     101            OutputVectorIterator getOutputVectorBegin() const;
     102            //! Returns an iterator to the end of the all-output vector
     103            OutputVectorIterator getOutputVectorEnd() const;
     104
     105            //! Writes to all output devices
    65106            static inline const std::string& log(const std::string& text)
    66                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
    67 
    68             /** @brief Puts an error on the outstream. @param text The text */
     107                { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
     108
     109            //! Writes an error message to the output
    69110            static inline const std::string& error(const std::string& text)
    70                 { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
    71 
    72             /** @brief Puts a warning on the outstream. @param text The text */
     111                { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
     112
     113            //! Writes a warning message to the output
    73114            static inline const std::string& warning(const std::string& text)
    74                 { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
    75 
    76             /** @brief Puts an info on the outstream. @param text The text */
     115                { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
     116
     117            //! Writes an informational message to the output
    77118            static inline const std::string& info(const std::string& text)
    78                 { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
    79 
    80             /** @brief Puts some debug output on the outstream. @param text The text */
     119                { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
     120
     121            //! Writes a debug message to the output
    81122            static inline const std::string& debug(const std::string& text)
    82                 { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
    83 
    84             /** @brief Returns a reference to the logfile. @return The logfile */
    85             inline std::ofstream& getLogfile()
    86                 { return this->logfile_; }
    87 
    88             /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
    89             inline OutputBuffer* getOutputBuffer()
    90                 { return this->outputBuffer_; }
    91 
    92             /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
     123                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
     124
     125            //! Registers an object that receives output via a provided std::ostream
     126            void registerOutputListener(OutputListener* listener);
     127            //! Unregisters an object that receives output via a provided std::ostream
     128            void unregisterOutputListener(OutputListener* listener);
     129
     130            //! Set the log path once the program has been properly initialised
     131            void setLogPath(const std::string& path);
     132            //! Disables the std::cout stream for output
     133            void disableCout();
     134            //! Enables the std::cout stream for output (startup behaviour)
     135            void enableCout();
     136
     137            //! Sets the level of the incoming output and returns the OutputHandler
    93138            inline OutputHandler& setOutputLevel(int level)
    94139                { this->outputLevel_ = level; return *this; }
    95140
    96             /** @brief Returns the level of the incoming output. @return The level */
     141            //! Returns the level of the incoming output
    97142            inline int getOutputLevel() const
    98143                { return this->outputLevel_; }
    99144
    100             static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    101             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    102 
    103             static void setLogPath(const std::string& path);
    104 
    105             void setOutputBuffer(OutputBuffer* buffer);
    106 
     145            //! Returns the maximum debug level over all registered listeners (devices)
     146            static int getSoftDebugLevel() { return softDebugLevel_s; }
     147            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
     148            int  getSoftDebugLevel(const std::string& name) const;
     149            //! Sets the soft debug level for a listener by its name   @remarks Only works for registered listeners!
     150            void setSoftDebugLevel(const std::string& name, int level);
     151
     152            /**
     153            @brief
     154                General template that copes with all output.
     155                Required because operator << might be ambiguous.
     156                @a output will be streamed into every listener with an appropriate debug level
     157            @return
     158                Returns a reference to the OutputHandler so you can use it again directly
     159            */
    107160            template <class T>
    108161            OutputHandler& output(const T& output);
    109162
    110             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     163            //! Overloaded << operator, redirects the output to the listeners
    111164            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
    112             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     165            //! Overloaded << operator, redirects the output to the listeners
    113166            inline OutputHandler& operator<<(short val)              { return this->output(val); }
    114             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     167            //! Overloaded << operator, redirects the output to the listeners
    115168            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
    116             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     169            //! Overloaded << operator, redirects the output to the listeners
    117170            inline OutputHandler& operator<<(int val)                { return this->output(val); }
    118             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     171            //! Overloaded << operator, redirects the output to the listeners
    119172            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
    120             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     173            //! Overloaded << operator, redirects the output to the listeners
    121174            inline OutputHandler& operator<<(long val)               { return this->output(val); }
    122             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     175            //! Overloaded << operator, redirects the output to the listeners
    123176            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
    124             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     177            //! Overloaded << operator, redirects the output to the listeners
    125178            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
    126             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     179            //! Overloaded << operator, redirects the output to the listeners
    127180            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
    128             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     181            //! Overloaded << operator, redirects the output to the listeners
    129182            inline OutputHandler& operator<<(float val)              { return this->output(val); }
    130             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     183            //! Overloaded << operator, redirects the output to the listeners
    131184            inline OutputHandler& operator<<(double val)             { return this->output(val); }
    132             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     185            //! Overloaded << operator, redirects the output to the listeners
    133186            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
    134             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     187            //! Overloaded << operator, redirects the output to the listeners
    135188            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
    136             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     189            //! Overloaded << operator, redirects the output to the listeners
    137190            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
    138191
    139             OutputHandler& operator<<(std::streambuf* sb);
    140 
    141             OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
    142             OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
    143             OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
     192            //! Overloaded << operator, redirects the output to the listeners
     193            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
     194
     195            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
     196            template <class T>
     197            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
     198
     199            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     200            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
     201            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     202            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
     203            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     204            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
     205
     206            //! Dummy operator required by Debug.h for the ternary operator
     207            inline operator int() const { return 0; }
     208
     209            //! Name of the OutputListener that writes to the log file
     210            static const std::string logFileOutputListenerName_s;
    144211
    145212        private:
    146             explicit OutputHandler();
    147             OutputHandler(const OutputHandler& oh);
    148             virtual ~OutputHandler();
    149 
    150             std::ofstream logfile_;              //!< The logfile where the output is logged
    151             std::string logfilename_;            //!< The name of the logfile
    152             OutputBuffer fallbackBuffer_;        //!< The OutputBuffer that gets used if there is no other OutputBuffer
    153             OutputBuffer* outputBuffer_;         //!< The OutputBuffer to put output in (usually used by the Shell)
    154             int outputLevel_;                    //!< The level of the incoming output
    155             int softDebugLevel_[4];              //!< The soft debug level for each OutputDevice - the configurable maximal output level
     213            OutputHandler();
     214            ~OutputHandler();
     215            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
     216
     217            std::list<OutputListener*> listeners_;        //!< Array with all registered output listeners
     218            int                        outputLevel_;      //!< The level of the incoming output
     219            LogFileWriter*             logFile_;          //!< Listener that writes to the log file
     220            ConsoleWriter*             consoleWriter_;    //!< Listener for std::cout (just program beginning)
     221            MemoryLogWriter*           output_;           //!< Listener that Stores ALL output below the current soft debug level
     222            static int                 softDebugLevel_s;  //!< Maximum of all soft debug levels. @note This is only static for faster access
    156223    };
    157224
    158225    /**
    159         @brief Redirects the output to the console and the logfile.
    160         @param output The value that should be shown in the console
    161         @return A reference to the OutputHandler itself
     226    @brief
     227        Interface for listening to output.
     228    @remarks
     229        Remember to register the listener (not done automatically!)
    162230    */
     231    class OutputListener
     232    {
     233        friend class OutputHandler;
     234
     235    public:
     236        OutputListener(const std::string& name)
     237            : outputStream_(NULL)
     238            , name_(name)
     239            , softDebugLevel_(OutputLevel::Info)
     240        {}
     241        virtual ~OutputListener() {}
     242
     243        //! Gets called whenever output is put into the stream
     244        virtual void outputChanged(int level) {}
     245        //! Returns the name of this output listener
     246        const std::string& getOutputListenerName() const { return this->name_; }
     247        //! Returns the soft debug level of the listener
     248        int getSoftDebugLevel() const { return this->softDebugLevel_; }
     249        //! Sets the soft debug level of the listener
     250        void setSoftDebugLevel(int level)
     251        {
     252            this->softDebugLevel_ = level;
     253            OutputHandler::getInstance().setSoftDebugLevel(this->name_, level);
     254        }
     255
     256    protected:
     257        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
     258
     259    private:
     260        const std::string name_;           //!< Name of the listener, constant and unique!
     261        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
     262    };
     263
    163264    template<class T>
    164     OutputHandler& OutputHandler::output(const T& output)
    165     {
    166         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    167             std::cout << output;
    168 
    169         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
     265    inline OutputHandler& OutputHandler::output(const T& output)
     266    {
     267        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
    170268        {
    171             this->logfile_ << output;
    172             this->logfile_.flush();
     269            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
     270            {
     271                std::ostream& stream = *((*it)->outputStream_);
     272                stream << output;
     273                stream.flush();
     274                (*it)->outputChanged(this->outputLevel_);
     275            }
    173276        }
    174 
    175         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    176             (*this->outputBuffer_) << output;
    177277
    178278        return *this;
    179279    }
    180 
    181     /**
    182         @brief Overloading of the non-member << operator to redirect the output of classes with self defined '<< to std::ostream' operators to the console and the logfile.
    183         @param out The OutputHandler itself
    184         @param output The class that should be shown in the console
    185         @return The OutputHandler itself
    186     */
    187     template<class T>
    188     OutputHandler& operator<<(OutputHandler& out, const T& output)
    189     {
    190         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
    191             std::cout << output;
    192 
    193         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
    194         {
    195             out.getLogfile() << output;
    196             out.getLogfile().flush();
    197         }
    198 
    199         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
    200             (*out.getOutputBuffer()) << output;
    201 
    202         return out;
    203     }
    204280}
    205281
  • code/trunk/src/libraries/util/UtilPrereqs.h

    r5929 r6105  
    8787    class IntVector3;
    8888    class MultiType;
    89     class OutputBuffer;
    90     class OutputBufferListener;
    9189    class OutputHandler;
     90    class OutputListener;
    9291    template <ScopeID::Value>
    9392    class Scope;
Note: See TracChangeset for help on using the changeset viewer.