From a86b8a1d93ea9c31e298f5c03474eb7f39cede72 Mon Sep 17 00:00:00 2001 From: tosh Date: Tue, 21 May 2013 01:00:10 +0200 Subject: [PATCH] refactors logging --- interface/src/Application.cpp | 11 +- interface/src/Log.cpp | 364 ------------------ interface/src/Log.h | 68 ---- interface/src/LogDisplay.cpp | 306 +++++++++++++++ interface/src/LogDisplay.h | 80 ++++ interface/src/LogStream.h | 106 ----- libraries/avatars/src/AvatarData.cpp | 4 +- libraries/avatars/src/Orientation.cpp | 3 - libraries/avatars/src/avatars_Log.cpp | 17 - libraries/avatars/src/avatars_Log.h | 20 - libraries/shared/src/Agent.cpp | 6 +- libraries/shared/src/AgentList.cpp | 4 +- .../src/voxels_Log.cpp => shared/src/Log.cpp} | 10 +- libraries/shared/src/{shared_Log.h => Log.h} | 15 +- libraries/shared/src/OctalCode.cpp | 4 +- libraries/shared/src/PerfStat.cpp | 4 +- libraries/shared/src/SharedUtil.cpp | 4 +- libraries/shared/src/UDPSocket.cpp | 4 +- libraries/shared/src/UrlReader.cpp | 3 +- libraries/shared/src/shared_Log.cpp | 17 - libraries/voxels/src/Plane.cpp | 5 +- libraries/voxels/src/ViewFrustum.cpp | 3 +- libraries/voxels/src/VoxelNode.cpp | 5 +- libraries/voxels/src/VoxelTree.cpp | 4 +- libraries/voxels/src/voxels_Log.h | 20 - 25 files changed, 414 insertions(+), 673 deletions(-) delete mode 100644 interface/src/Log.cpp delete mode 100644 interface/src/Log.h create mode 100644 interface/src/LogDisplay.cpp create mode 100644 interface/src/LogDisplay.h delete mode 100644 interface/src/LogStream.h delete mode 100644 libraries/avatars/src/avatars_Log.cpp delete mode 100644 libraries/avatars/src/avatars_Log.h rename libraries/{voxels/src/voxels_Log.cpp => shared/src/Log.cpp} (50%) rename libraries/shared/src/{shared_Log.h => Log.h} (50%) delete mode 100644 libraries/shared/src/shared_Log.cpp delete mode 100644 libraries/voxels/src/voxels_Log.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 711f6d17a7..5db6bf2562 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -37,13 +37,10 @@ #include #include #include -#include -#include -#include #include "Application.h" #include "InterfaceConfig.h" -#include "Log.h" +#include "LogDisplay.h" #include "OculusManager.h" #include "Util.h" #include "renderer/ProgramObject.h" @@ -159,10 +156,6 @@ Application::Application(int& argc, char** argv) : _voxels.setViewFrustum(&_viewFrustum); - shared_lib::printLog = & ::printLog; - voxels_lib::printLog = & ::printLog; - avatars_lib::printLog = & ::printLog; - unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT; const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); @@ -1772,7 +1765,7 @@ void Application::displayOverlay() { glPointSize(1.0f); if (_renderStatsOn->isChecked()) { displayStats(); } - if (_logOn->isChecked()) { logdisplay::Render(_glWidget->width(), _glWidget->height()); } + if (_logOn->isChecked()) { LogDisplay::instance.render(_glWidget->width(), _glWidget->height()); } // Show chat entry field if (_chatEntryOn) { diff --git a/interface/src/Log.cpp b/interface/src/Log.cpp deleted file mode 100644 index af3b2f90fb..0000000000 --- a/interface/src/Log.cpp +++ /dev/null @@ -1,364 +0,0 @@ -// -// Log.cpp -// interface -// -// Created by Tobias Schwinger on 4/14/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#include "Log.h" - - -#include -#include -#include - -#include "InterfaceConfig.h" - -#include "Util.h" -#include "ui/TextRenderer.h" - - -namespace logdisplay { - - class Logger { - public: - Logger(); - ~Logger(); - - inline void render(unsigned screenWidth, unsigned screenHeight); - - inline void setStream(FILE* stream); - inline void setLogWidth(unsigned pixels); - inline void setCharacterSize(unsigned width, unsigned height); - - // format, eventually forward, and add the log message (called by printLog) - inline int vprint(char const* fmt, va_list); - - private: - // don't copy/assign - Logger(Logger const&); // = delete; - Logger& operator=(Logger const&); // = delete; - - // add formatted message for console diplay (called by vprint) - inline void addMessage(char const*); - - TextRenderer _textRenderer; - FILE* _stream; // FILE as secondary destination for log messages - char* _chars; // character buffer base address - char* _charsEnd; // character buffer, exclusive end - char** _lines; // line buffer base address - char** _linesEnd; // line buffer, exclusive end - - char* _writePos; // character position to write to - char* _writeLineStartPos; // character position where line being written starts - char** _lastLinePos; // last line in the log - unsigned _writtenInLine; // character counter for line wrapping - unsigned _lineLength; // number of characters before line wrap - - unsigned _logWidth; // width of the log in pixels - unsigned _charWidth; // width of a character in pixels - unsigned _charHeight; // height of a character in pixels - - pthread_mutex_t _mutex; - }; - - - // - // Initialization / state management - // - - Logger::Logger() : - - _textRenderer(MONO_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT), - _stream(DEFAULT_STREAM), - _chars(0l), - _lines(0l), - _logWidth(DEFAULT_CONSOLE_WIDTH) { - - pthread_mutex_init(& _mutex, 0l); - - // allocate twice as much (so we have spare space for a copy not to block - // logging from other threads during 'render') - _chars = new char[CHARACTER_BUFFER_SIZE * 2]; - _charsEnd = _chars + CHARACTER_BUFFER_SIZE; - _lines = new char*[LINE_BUFFER_SIZE * 2]; - _linesEnd = _lines + LINE_BUFFER_SIZE; - - // initialize the log to all empty lines - _chars[0] = '\0'; - _writePos = _chars; - _writeLineStartPos = _chars; - _lastLinePos = _lines; - _writtenInLine = 0; - memset(_lines, 0, LINE_BUFFER_SIZE * sizeof(char*)); - - setCharacterSize(DEFAULT_CHAR_WIDTH, DEFAULT_CHAR_HEIGHT); - } - - - Logger::~Logger() { - - delete[] _chars; - delete[] _lines; - } - - inline void Logger::setStream(FILE* stream) { - - pthread_mutex_lock(& _mutex); - _stream = stream; - pthread_mutex_unlock(& _mutex); - } - - inline void Logger::setLogWidth(unsigned pixels) { - - pthread_mutex_lock(& _mutex); - _logWidth = pixels; - _lineLength = _logWidth / _charWidth; - pthread_mutex_unlock(& _mutex); - } - - inline void Logger::setCharacterSize(unsigned width, unsigned height) { - - pthread_mutex_lock(& _mutex); - _charWidth = width; - _charHeight = height; - _lineLength = _logWidth / _charWidth; - pthread_mutex_unlock(& _mutex); - } - - // - // Logging - // - - inline int Logger::vprint(char const* fmt, va_list args) { - pthread_mutex_lock(& _mutex); - - // print to buffer - char buf[MAX_MESSAGE_LENGTH]; - int n = vsnprintf(buf, MAX_MESSAGE_LENGTH, fmt, args); - if (n > 0) { - - // all fine? log the message - addMessage(buf); - - } else { - - // error? -> mutter on stream or stderr - fprintf(_stream != 0l ? _stream : stderr, - "Log: Failed to log message with format string = \"%s\".\n", fmt); - } - - pthread_mutex_unlock(& _mutex); - return n; - } - - inline void Logger::addMessage(char const* ptr) { - - // precondition: mutex is locked so noone gets in our way - - // T-pipe, if requested - if (_stream != 0l) { - fprintf(_stream, "%s", ptr); - } - - while (*ptr != '\0') { - // process the characters - char c = *ptr++; - - if (c == '\t') { - - // found TAB -> write SPACE - c = ' '; - - } else if (c == '\n') { - - // found LF -> write NUL (c == '\0' tells us to wrap, below) - c = '\0'; - } - *_writePos++ = c; - - if (_writePos == _charsEnd) { - // reached the end of the circular character buffer? -> start over - _writePos = _chars; - } - - if (++_writtenInLine >= _lineLength || c == '\0') { - - // new line? store its start to the line buffer and mark next line as empty - ++_lastLinePos; - - if (_lastLinePos == _linesEnd) { - _lastLinePos = _lines; - _lastLinePos[1] = 0l; - } else if (_lastLinePos + 1 != _linesEnd) { - _lastLinePos[1] = 0l; - } else { - _lines[0] = 0l; - } - *_lastLinePos = _writeLineStartPos; - - // debug mode: make sure all line pointers we write here are valid - assert(! (_lastLinePos < _lines || _lastLinePos >= _linesEnd)); - assert(! (*_lastLinePos < _chars || *_lastLinePos >= _charsEnd)); - - // terminate line, unless done already - if (c != '\0') { - *_writePos++ = '\0'; - - if (_writePos == _charsEnd) { - _writePos = _chars; - } - } - - // remember start position in character buffer for next line and reset character count - _writeLineStartPos = _writePos; - _writtenInLine = 0; - } - } - - } - - // - // Rendering - // - - inline void Logger::render(unsigned screenWidth, unsigned screenHeight) { - - // rendering might take some time, so create a local copy of the portion we need - // instead of having to hold the mutex all the time - pthread_mutex_lock(& _mutex); - - // determine number of visible lines (integer division rounded up) - unsigned showLines = (screenHeight + _charHeight - 1) / _charHeight; - - char** lastLine = _lastLinePos; - char** firstLine = _lastLinePos; - - if (! *lastLine) { - // empty log - pthread_mutex_unlock(& _mutex); - return; - } - - // scan for first line - for (int n = 2; n <= showLines; ++n) { - - char** prevFirstLine = firstLine; - --firstLine; - if (firstLine < _lines) { - firstLine = _linesEnd - 1; - } - if (! *firstLine) { - firstLine = prevFirstLine; - showLines = n - 1; - break; - } - - // debug mode: make sure all line pointers we find here are valid - assert(! (firstLine < _lines || firstLine >= _linesEnd)); - assert(! (*firstLine < _chars || *firstLine >= _charsEnd)); - } - - // copy the line buffer portion into a contiguous region at _linesEnd - if (firstLine <= lastLine) { - - memcpy(_linesEnd, firstLine, showLines * sizeof(char*)); - - } else { - - unsigned atEnd = _linesEnd - firstLine; - memcpy(_linesEnd, firstLine, atEnd * sizeof(char*)); - memcpy(_linesEnd + atEnd, _lines, (showLines - atEnd) * sizeof(char*)); - } - - // copy relevant char buffer portion and determine information to remap the pointers - char* firstChar = *firstLine; - char* lastChar = *lastLine + strlen(*lastLine) + 1; - ptrdiff_t charOffset = _charsEnd - firstChar, charOffsetBeforeFirst = 0; - if (firstChar <= lastChar) { - - memcpy(_charsEnd, firstChar, lastChar - firstChar + 1); - - } else { - - unsigned atEnd = _charsEnd - firstChar; - memcpy(_charsEnd, firstChar, atEnd); - memcpy(_charsEnd + atEnd, _chars, lastChar + 1 - _chars); - - charOffsetBeforeFirst = _charsEnd + atEnd - _chars; - } - - // determine geometry information from font metrics - QFontMetrics const& fontMetrics = _textRenderer.metrics(); - int yStep = fontMetrics.lineSpacing(); - // scale - float xScale = float(_charWidth) / fontMetrics.width('*'); - float yScale = float(_charHeight) / yStep; - // scaled translation - int xStart = int((screenWidth - _logWidth) / xScale); - int yStart = screenHeight / yScale - fontMetrics.descent(); - - // first line to render - char** line = _linesEnd + showLines; - - // ok, now the lock can be released - we have all we need - // and won't hold it while talking to OpenGL - pthread_mutex_unlock(& _mutex); - - glPushMatrix(); - glScalef(xScale, yScale, 1.0f); - for (int y = yStart; y > 0; y -= yStep) { - - // debug mode: check line pointer is valid - assert(! (line < _linesEnd || line >= _linesEnd + (_linesEnd - _lines))); - - // get character pointer - if (--line < _linesEnd) { - break; - } - char* chars = *line; - - // debug mode: check char pointer we find is valid - assert(! (chars < _chars || chars >= _charsEnd)); - - // remap character pointer it to copied buffer - chars += chars >= firstChar ? charOffset : charOffsetBeforeFirst; - - // debug mode: check char pointer is still valid (in new range) - assert(! (chars < _charsEnd || chars >= _charsEnd + (_charsEnd - _chars))); - - // render the string - glColor3f(TEXT_COLOR_RED, TEXT_COLOR_GREEN, TEXT_COLOR_BLUE); - _textRenderer.draw(xStart, y, chars); - - //fprintf(stderr, "Logger::render, message = \"%s\"\n", chars); - } - glPopMatrix(); - } - - - // - // There's one Logger and it exists globally... - // - Logger logger; - - // Entrypoints - void Render(unsigned screenWidth, unsigned screenHeight) { logger.render(screenWidth, screenHeight); } - void SetStream(FILE* stream) { logger.setStream(stream); } - void SetLogWidth(unsigned pixels) { logger.setLogWidth(pixels); } - void SetCharacterSize(unsigned width, unsigned height) { logger.setCharacterSize(width, height); } - -} // namespace logdisplay - - -int printLog(char const* fmt, ...) { - - int result; - va_list args; - va_start(args,fmt); - result = logdisplay::logger.vprint(fmt, args); - va_end(args); - return result; -} - diff --git a/interface/src/Log.h b/interface/src/Log.h deleted file mode 100644 index 2293c39a76..0000000000 --- a/interface/src/Log.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// Log.h -// interface -// -// Created by Tobias Schwinger on 4/14/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__Log__ -#define __interface__Log__ - -#include -#include - -// -// Log function. Call it as you would call 'printf'. -// -int printLog(char const* fmt, ...); - -// -// Logging control. -// -namespace logdisplay { - - void Render(unsigned screenWidth, unsigned screenHeight); - - // settings - - static float const TEXT_COLOR_RED = 0.7f; // text foreground color, red component - static float const TEXT_COLOR_GREEN = 0.6f; // text foreground color, green component - static float const TEXT_COLOR_BLUE = 1.0f; // text foregdound color, blue component - - static FILE* DEFAULT_STREAM = stdout; // stream to also log to - static unsigned const DEFAULT_CHAR_WIDTH = 7; // width of a single character - static unsigned const DEFAULT_CHAR_HEIGHT = 16; // height of a single character - static unsigned const DEFAULT_CONSOLE_WIDTH = 400; // width of the (right-aligned) log console - - void SetStream(FILE* stream); - void SetLogWidth(unsigned pixels); - void SetCharacterSize(unsigned width, unsigned height); - - // limits - - unsigned const CHARACTER_BUFFER_SIZE = 16384; // number of character that are buffered - unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered - unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message -} - -// -// Macro to log OpenGL errors. -// Example: printGlError( glPushMatrix() ); -// -#define printLogGlError(stmt) \ - stmt; \ - { \ - GLenum e = glGetError(); \ - if (e != GL_NO_ERROR) { \ - printLog(__FILE__ ":" printLogGlError_stringize(__LINE__) \ - " [OpenGL] %s\n", gluErrorString(e)); \ - } \ - } \ - (void) 0 - -#define printLogGlError_stringize(x) printLogGlError_stringize_i(x) -#define printLogGlError_stringize_i(x) # x - -#endif - diff --git a/interface/src/LogDisplay.cpp b/interface/src/LogDisplay.cpp new file mode 100644 index 0000000000..fc1f1abf23 --- /dev/null +++ b/interface/src/LogDisplay.cpp @@ -0,0 +1,306 @@ +// +// LogDisplay.cpp +// interface +// +// Created by Tobias Schwinger on 4/14/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "LogDisplay.h" + +#include +#include +#include + +#include "Util.h" + +using namespace std; +FILE* const LogDisplay::DEFAULT_STREAM = stdout; + +// +// Singleton constructor +// +LogDisplay LogDisplay::instance; + +// +// State management +// + +LogDisplay::LogDisplay() : + + _textRenderer(MONO_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT), + _stream(DEFAULT_STREAM), + _chars(0l), + _lines(0l), + _logWidth(DEFAULT_CONSOLE_WIDTH) { + + pthread_mutex_init(& _mutex, 0l); + + // allocate twice as much (so we have spare space for a copy not to block + // logging from other threads during 'render') + _chars = new char[CHARACTER_BUFFER_SIZE * 2]; + _charsEnd = _chars + CHARACTER_BUFFER_SIZE; + _lines = new char*[LINE_BUFFER_SIZE * 2]; + _linesEnd = _lines + LINE_BUFFER_SIZE; + + // initialize the log to all empty lines + _chars[0] = '\0'; + _writePos = _chars; + _writeLineStartPos = _chars; + _lastLinePos = _lines; + _writtenInLine = 0; + memset(_lines, 0, LINE_BUFFER_SIZE * sizeof(char*)); + + setCharacterSize(DEFAULT_CHAR_WIDTH, DEFAULT_CHAR_HEIGHT); + + printLog = & printLogHandler; +} + + +LogDisplay::~LogDisplay() { + + delete[] _chars; + delete[] _lines; +} + +void LogDisplay::setStream(FILE* stream) { + + pthread_mutex_lock(& _mutex); + _stream = stream; + pthread_mutex_unlock(& _mutex); +} + +void LogDisplay::setLogWidth(unsigned pixels) { + + pthread_mutex_lock(& _mutex); + _logWidth = pixels; + _lineLength = _logWidth / _charWidth; + pthread_mutex_unlock(& _mutex); +} + +void LogDisplay::setCharacterSize(unsigned width, unsigned height) { + + pthread_mutex_lock(& _mutex); + _charWidth = width; + _charHeight = height; + _lineLength = _logWidth / _charWidth; + pthread_mutex_unlock(& _mutex); +} + +// +// Logging +// + +int LogDisplay::printLogHandler(char const* fmt, ...) { + + va_list args; + int n; + char buf[MAX_MESSAGE_LENGTH]; + va_start(args,fmt); + + // print to buffer + n = vsnprintf(buf, MAX_MESSAGE_LENGTH, fmt, args); + if (n > 0) { + + // all fine? log the message + instance.addMessage(buf); + + } else { + + // error? -> mutter on stream or stderr + fprintf(instance._stream != 0l ? instance._stream : stderr, + "Log: Failed to log message with format string = \"%s\".\n", fmt); + } + + va_end(args); + return n; +} + +inline void LogDisplay::addMessage(char const* ptr) { + + pthread_mutex_lock(& _mutex); + + // T-pipe, if requested + if (_stream != 0l) { + fprintf(_stream, "%s", ptr); + } + + while (*ptr != '\0') { + // process the characters + char c = *ptr++; + + if (c == '\t') { + + // found TAB -> write SPACE + c = ' '; + + } else if (c == '\n') { + + // found LF -> write NUL (c == '\0' tells us to wrap, below) + c = '\0'; + } + *_writePos++ = c; + + if (_writePos == _charsEnd) { + // reached the end of the circular character buffer? -> start over + _writePos = _chars; + } + + if (++_writtenInLine >= _lineLength || c == '\0') { + + // new line? store its start to the line buffer and mark next line as empty + ++_lastLinePos; + + if (_lastLinePos == _linesEnd) { + _lastLinePos = _lines; + _lastLinePos[1] = 0l; + } else if (_lastLinePos + 1 != _linesEnd) { + _lastLinePos[1] = 0l; + } else { + _lines[0] = 0l; + } + *_lastLinePos = _writeLineStartPos; + + // debug mode: make sure all line pointers we write here are valid + assert(! (_lastLinePos < _lines || _lastLinePos >= _linesEnd)); + assert(! (*_lastLinePos < _chars || *_lastLinePos >= _charsEnd)); + + // terminate line, unless done already + if (c != '\0') { + *_writePos++ = '\0'; + + if (_writePos == _charsEnd) { + _writePos = _chars; + } + } + + // remember start position in character buffer for next line and reset character count + _writeLineStartPos = _writePos; + _writtenInLine = 0; + } + } + + pthread_mutex_unlock(& _mutex); +} + +// +// Rendering +// + +void LogDisplay::render(unsigned screenWidth, unsigned screenHeight) { + + // rendering might take some time, so create a local copy of the portion we need + // instead of having to hold the mutex all the time + pthread_mutex_lock(& _mutex); + + // determine number of visible lines (integer division rounded up) + unsigned showLines = (screenHeight + _charHeight - 1) / _charHeight; + + char** lastLine = _lastLinePos; + char** firstLine = _lastLinePos; + + if (! *lastLine) { + // empty log + pthread_mutex_unlock(& _mutex); + return; + } + + // scan for first line + for (int n = 2; n <= showLines; ++n) { + + char** prevFirstLine = firstLine; + --firstLine; + if (firstLine < _lines) { + firstLine = _linesEnd - 1; + } + if (! *firstLine) { + firstLine = prevFirstLine; + showLines = n - 1; + break; + } + + // debug mode: make sure all line pointers we find here are valid + assert(! (firstLine < _lines || firstLine >= _linesEnd)); + assert(! (*firstLine < _chars || *firstLine >= _charsEnd)); + } + + // copy the line buffer portion into a contiguous region at _linesEnd + if (firstLine <= lastLine) { + + memcpy(_linesEnd, firstLine, showLines * sizeof(char*)); + + } else { + + unsigned atEnd = _linesEnd - firstLine; + memcpy(_linesEnd, firstLine, atEnd * sizeof(char*)); + memcpy(_linesEnd + atEnd, _lines, (showLines - atEnd) * sizeof(char*)); + } + + // copy relevant char buffer portion and determine information to remap the pointers + char* firstChar = *firstLine; + char* lastChar = *lastLine + strlen(*lastLine) + 1; + ptrdiff_t charOffset = _charsEnd - firstChar, charOffsetBeforeFirst = 0; + if (firstChar <= lastChar) { + + memcpy(_charsEnd, firstChar, lastChar - firstChar + 1); + + } else { + + unsigned atEnd = _charsEnd - firstChar; + memcpy(_charsEnd, firstChar, atEnd); + memcpy(_charsEnd + atEnd, _chars, lastChar + 1 - _chars); + + charOffsetBeforeFirst = _charsEnd + atEnd - _chars; + } + + // determine geometry information from font metrics + QFontMetrics const& fontMetrics = _textRenderer.metrics(); + int yStep = fontMetrics.lineSpacing(); + // scale + float xScale = float(_charWidth) / fontMetrics.width('*'); + float yScale = float(_charHeight) / yStep; + // scaled translation + int xStart = int((screenWidth - _logWidth) / xScale); + int yStart = screenHeight / yScale - fontMetrics.descent(); + + // first line to render + char** line = _linesEnd + showLines; + + // ok, now the lock can be released - we have all we need + // and won't hold it while talking to OpenGL + pthread_mutex_unlock(& _mutex); + + glPushMatrix(); + glScalef(xScale, yScale, 1.0f); + for (int y = yStart; y > 0; y -= yStep) { + + // debug mode: check line pointer is valid + assert(! (line < _linesEnd || line >= _linesEnd + (_linesEnd - _lines))); + + // get character pointer + if (--line < _linesEnd) { + break; + } + char* chars = *line; + + // debug mode: check char pointer we find is valid + assert(! (chars < _chars || chars >= _charsEnd)); + + // remap character pointer it to copied buffer + chars += chars >= firstChar ? charOffset : charOffsetBeforeFirst; + + // debug mode: check char pointer is still valid (in new range) + assert(! (chars < _charsEnd || chars >= _charsEnd + (_charsEnd - _chars))); + + // render the string + glColor3ub(GLubyte(TEXT_COLOR >> 16), + GLubyte((TEXT_COLOR >> 8) & 0xff), + GLubyte(TEXT_COLOR & 0xff)); + _textRenderer.draw(xStart, y, chars); + +//fprintf(stderr, "LogDisplay::render, message = \"%s\"\n", chars); + } + glPopMatrix(); +} + + diff --git a/interface/src/LogDisplay.h b/interface/src/LogDisplay.h new file mode 100644 index 0000000000..625e84be25 --- /dev/null +++ b/interface/src/LogDisplay.h @@ -0,0 +1,80 @@ +// +// LogDisplay.h +// interface +// +// Created by Tobias Schwinger on 4/14/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__LogDisplay__ +#define __interface__LogDisplay__ + +#include +#include + +#include "Log.h" +#include "ui/TextRenderer.h" + +class LogDisplay { +public: + + static LogDisplay instance; + + void render(unsigned screenWidth, unsigned screenHeight); + + // settings + + static unsigned const TEXT_COLOR = 0xb299ff; // text foreground color (bytes, RGB) + + static FILE* const DEFAULT_STREAM; // = stdout; // stream to also log to (defined in .cpp) + static unsigned const DEFAULT_CHAR_WIDTH = 7; // width of a single character + static unsigned const DEFAULT_CHAR_HEIGHT = 16; // height of a single character + static unsigned const DEFAULT_CONSOLE_WIDTH = 400; // width of the (right-aligned) log console + + void setStream(FILE* stream); + void setLogWidth(unsigned pixels); + void setCharacterSize(unsigned width, unsigned height); + + // limits + + static unsigned const CHARACTER_BUFFER_SIZE = 16384; // number of character that are buffered + static unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered + static unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message + +private: + // use static 'instance' to access the single instance + LogDisplay(); + ~LogDisplay(); + + // don't copy/assign + LogDisplay(LogDisplay const&); // = delete; + LogDisplay& operator=(LogDisplay const&); // = delete; + + // format and log message - entrypoint used to replace global 'printLog' + static int static printLogHandler(char const* fmt, ...); + + // log formatted message (called by printLogHandler) + inline void addMessage(char const*); + + TextRenderer _textRenderer; + FILE* _stream; // FILE as secondary destination for log messages + char* _chars; // character buffer base address + char* _charsEnd; // character buffer, exclusive end + char** _lines; // line buffer base address + char** _linesEnd; // line buffer, exclusive end + + char* _writePos; // character position to write to + char* _writeLineStartPos; // character position where line being written starts + char** _lastLinePos; // last line in the log + unsigned _writtenInLine; // character counter for line wrapping + unsigned _lineLength; // number of characters before line wrap + + unsigned _logWidth; // width of the log in pixels + unsigned _charWidth; // width of a character in pixels + unsigned _charHeight; // height of a character in pixels + + pthread_mutex_t _mutex; +}; + +#endif + diff --git a/interface/src/LogStream.h b/interface/src/LogStream.h deleted file mode 100644 index 2b8cc25669..0000000000 --- a/interface/src/LogStream.h +++ /dev/null @@ -1,106 +0,0 @@ -// -// LogStream.h -// interface -// -// Created by Tobias Schwinger on 4/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__LogStream__ -#define __interface__LogStream__ - -#include - -#include "Log.h" - -// -// Makes the logging facility accessible as a C++ stream. -// -// Example: -// -// // somewhere central - ideally one per thread (else pass 'true' as -// // second constructor argument and compromise some efficiency) -// LogStream lOut(printLog); -// -// // elsewhere: -// lOut << "Hello there!" << std::endl; -// -class LogStream { - std::ostringstream _outStream; - Log& _logRef; - bool _isThreadSafe; -public: - inline LogStream(Log& log, bool threadSafe = false); - - class StreamRef; friend class StreamRef; - - template< typename T > friend inline LogStream::StreamRef const operator<<(LogStream&, T const&); - -private: - // don't - LogStream(LogStream const&); // = delete; - LogStream& operator=(LogStream const&); // = delete; - - inline void ostreamBegin(); - inline void ostreamEnd(); -}; - -inline LogStream::LogStream(Log& log, bool threadSafe) : - _outStream(std::ios_base::out), _logRef(log), _isThreadSafe(threadSafe) { } - -inline void LogStream::ostreamBegin() { - - if (_isThreadSafe) { - // the user wants to share this LogStream among threads, - // so lock the global log here, already - pthread_mutex_lock(& _logRef._mutex); - } - _outStream.str(""); -} - -inline void LogStream::ostreamEnd() { - - if (! _isThreadSafe) { - // haven't locked, so far (we have memory for each thread) - pthread_mutex_lock(& _logRef._mutex); - } - _logRef.addMessage(_outStream.str().c_str()); - pthread_mutex_unlock(& _logRef._mutex); -} - - -// -// The Log::StreamRef class makes operator<< work. It... -// -class LogStream::StreamRef { - mutable LogStream* _logStream; - typedef std::ostream& (*manipulator)(std::ostream&); - - friend class LogStream; - - template< typename T > friend inline LogStream::StreamRef const operator<<(LogStream&, T const&); - StreamRef(LogStream* log) : _logStream(log) { } -public: - // ...forwards << operator calls to stringstream... - template< typename T > StreamRef const operator<<(T const& x) const { _logStream->_outStream << x; return *this; } - // ...has to dance around to make manipulators (such as std::hex, std::endl) work... - StreamRef const operator<<(manipulator x) const { _logStream->_outStream << x; return *this; } - // ...informs the logger that a stream has ended when it has the responsibility... - ~StreamRef() { if (_logStream != 0l) { _logStream->ostreamEnd(); } } - // ...which is passed on upon copy. - StreamRef(StreamRef const& other) : _logStream(other._logStream) { other._logStream = 0l; } - -private: - // don't - StreamRef& operator=(StreamRef const&); // = delete; -}; - -template< typename T > inline LogStream::StreamRef const operator<<(LogStream& s, T const& x) { - - s.ostreamBegin(); - s._outStream << x; - return LogStream::StreamRef(& s); // calls streamEnd at the end of the stream expression -} - - -#endif diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 22dd33ae65..dc875fd4db 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -14,10 +14,8 @@ #include #include "AvatarData.h" -#include "avatars_Log.h" using namespace std; -using avatars_lib::printLog; int packFloatAngleToTwoByte(unsigned char* buffer, float angle) { const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0); @@ -224,4 +222,4 @@ void AvatarData::setHeadPitch(float p) { const float MAX_PITCH = 60; const float MIN_PITCH = -60; _headPitch = glm::clamp(p, MIN_PITCH, MAX_PITCH); -} \ No newline at end of file +} diff --git a/libraries/avatars/src/Orientation.cpp b/libraries/avatars/src/Orientation.cpp index 6466eb802c..1d26e99e49 100755 --- a/libraries/avatars/src/Orientation.cpp +++ b/libraries/avatars/src/Orientation.cpp @@ -7,9 +7,6 @@ #include "Orientation.h" #include "SharedUtil.h" -//#include "avatars_Log.h" - -//using avatars_lib::printLog; static const bool USING_QUATERNIONS = true; diff --git a/libraries/avatars/src/avatars_Log.cpp b/libraries/avatars/src/avatars_Log.cpp deleted file mode 100644 index da8712b755..0000000000 --- a/libraries/avatars/src/avatars_Log.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// avatars_Log.cpp -// hifi -// -// Created by Tobias Schwinger on 4/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#include "shared_Log.h" - -#include - -namespace avatars_lib { - using namespace std; - - int (* printLog)(char const*, ...) = & printf; -} diff --git a/libraries/avatars/src/avatars_Log.h b/libraries/avatars/src/avatars_Log.h deleted file mode 100644 index 1d07cf46bf..0000000000 --- a/libraries/avatars/src/avatars_Log.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// avatars_Log.h -// hifi -// -// Created by Tobias Schwinger on 4/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __hifi__avatars_Log__ -#define __hifi__avatars_Log__ - -namespace avatars_lib { - - // variable that can be set from outside to redirect the log output - // of this library - extern int (* printLog)(char const*, ...); -} - -#endif /* defined(__hifi__avatars_Log__) */ - diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index f21f06eba6..9bddd45b84 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -10,7 +10,7 @@ #include "Agent.h" #include "AgentTypes.h" #include -#include "shared_Log.h" +#include "Log.h" #include "UDPSocket.h" #include "SharedUtil.h" @@ -20,8 +20,6 @@ #include #endif -using shared_lib::printLog; - int unpackAgentId(unsigned char* packedData, uint16_t* agentId) { memcpy(agentId, packedData, sizeof(uint16_t)); return sizeof(uint16_t); @@ -150,4 +148,4 @@ void Agent::printLog(Agent const& agent) { agent._type, publicAddressBuffer, publicAddressPort); -} \ No newline at end of file +} diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 3da956a04a..be7459b450 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -15,7 +15,7 @@ #include "AgentTypes.h" #include "PacketHeaders.h" #include "SharedUtil.h" -#include "shared_Log.h" +#include "Log.h" #ifdef _WIN32 #include "Syssocket.h" @@ -23,8 +23,6 @@ #include #endif -using shared_lib::printLog; - const char SOLO_AGENT_TYPES[3] = { AGENT_TYPE_AVATAR_MIXER, AGENT_TYPE_AUDIO_MIXER, diff --git a/libraries/voxels/src/voxels_Log.cpp b/libraries/shared/src/Log.cpp similarity index 50% rename from libraries/voxels/src/voxels_Log.cpp rename to libraries/shared/src/Log.cpp index 6fd637a1ec..2db1ab4288 100644 --- a/libraries/voxels/src/voxels_Log.cpp +++ b/libraries/shared/src/Log.cpp @@ -1,17 +1,15 @@ // -// voxels_Log.cpp +// Log.cpp // hifi // // Created by Tobias Schwinger on 4/17/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#include "voxels_Log.h" +#include "Log.h" #include -namespace voxels_lib { - using namespace std; +using namespace std; +int (* printLog)(char const*, ...) = & printf; - int (* printLog)(char const*, ...) = & printf; -} diff --git a/libraries/shared/src/shared_Log.h b/libraries/shared/src/Log.h similarity index 50% rename from libraries/shared/src/shared_Log.h rename to libraries/shared/src/Log.h index 29c1a4ed57..e2bc77e1e8 100644 --- a/libraries/shared/src/shared_Log.h +++ b/libraries/shared/src/Log.h @@ -1,5 +1,5 @@ // -// shared_Log.h +// Log.h // hifi // // Created by Tobias Schwinger on 4/17/13. @@ -9,12 +9,13 @@ #ifndef __hifi__shared_Log__ #define __hifi__shared_Log__ -namespace shared_lib { - - // variable that can be set from outside to redirect the log output - // of this library - extern int (* printLog)(char const*, ...); -} +// +// Pointer to log function +// +// An application may reset this variable to receive the log messages +// issued using 'printLog'. It defaults to a pointer to 'printf'. +// +extern int (* printLog)(char const*, ...); #endif /* defined(__hifi__shared_Log__) */ diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index da2b017875..d218639882 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -11,9 +11,7 @@ #include #include "SharedUtil.h" #include "OctalCode.h" -#include "shared_Log.h" - -using shared_lib::printLog; +#include "Log.h" int numberOfThreeBitSectionsInCode(unsigned char * octalCode) { if (*octalCode == 255) { diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 87998599aa..3c30c62993 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -14,9 +14,7 @@ #include #include -#include "shared_Log.h" - -using shared_lib::printLog; +#include "Log.h" // Static class members initialization here! std::map > PerfStat::groupHistoryMap; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 113b3fdda0..6e23413ea7 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -14,7 +14,7 @@ #ifdef _WIN32 #include "Syssocket.h" #endif -#include "shared_Log.h" +#include "Log.h" #include "SharedUtil.h" #include "OctalCode.h" @@ -22,8 +22,6 @@ #include #endif -using shared_lib::printLog; - double usecTimestamp(timeval *time) { return (time->tv_sec * 1000000.0 + time->tv_usec); } diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 88930d4af4..48fc18ef04 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -21,9 +21,7 @@ #include #endif -#include "shared_Log.h" - -using shared_lib::printLog; +#include "Log.h" sockaddr_in destSockaddr, senderAddress; diff --git a/libraries/shared/src/UrlReader.cpp b/libraries/shared/src/UrlReader.cpp index 305db63667..638134f4dd 100644 --- a/libraries/shared/src/UrlReader.cpp +++ b/libraries/shared/src/UrlReader.cpp @@ -13,8 +13,7 @@ #include #include -#include "shared_Log.h" -using shared_lib::printLog; +#include "Log.h" #ifndef _WIN32 // (Windows port is incomplete and the build files do not support CURL, yet) diff --git a/libraries/shared/src/shared_Log.cpp b/libraries/shared/src/shared_Log.cpp deleted file mode 100644 index 93a5c74714..0000000000 --- a/libraries/shared/src/shared_Log.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// shared_Log.cpp -// hifi -// -// Created by Tobias Schwinger on 4/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#include "shared_Log.h" - -#include - -namespace shared_lib { - using namespace std; - - int (* printLog)(char const*, ...) = & printf; -} diff --git a/libraries/voxels/src/Plane.cpp b/libraries/voxels/src/Plane.cpp index d999306794..5a99bf29c4 100755 --- a/libraries/voxels/src/Plane.cpp +++ b/libraries/voxels/src/Plane.cpp @@ -9,11 +9,10 @@ // #include "Plane.h" + #include -#include "voxels_Log.h" - -using voxels_lib::printLog; +#include "Log.h" // These are some useful utilities that vec3 is missing void printVec3(const char* name, const glm::vec3& v) { diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index cce3eac76f..ba712c9655 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -14,9 +14,8 @@ #include "ViewFrustum.h" #include "SharedUtil.h" -#include "voxels_Log.h" +#include "Log.h" -using voxels_lib::printLog; using namespace std; ViewFrustum::ViewFrustum() : diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 6bab72cf61..5c983bda6b 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -10,14 +10,11 @@ #include #include #include "SharedUtil.h" -#include "voxels_Log.h" +#include "Log.h" #include "VoxelNode.h" #include "VoxelConstants.h" #include "OctalCode.h" #include "AABox.h" -using voxels_lib::printLog; - -// using voxels_lib::printLog; VoxelNode::VoxelNode() { unsigned char* rootCode = new unsigned char[1]; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 249a70212e..2c8943497d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -13,7 +13,7 @@ #include #include #include "SharedUtil.h" -#include "voxels_Log.h" +#include "Log.h" #include "PacketHeaders.h" #include "OctalCode.h" #include "VoxelTree.h" @@ -24,8 +24,6 @@ #include -using voxels_lib::printLog; - int boundaryDistanceForRenderLevel(unsigned int renderLevel) { float voxelSizeScale = 50000.0f; return voxelSizeScale / powf(2, renderLevel); diff --git a/libraries/voxels/src/voxels_Log.h b/libraries/voxels/src/voxels_Log.h deleted file mode 100644 index 3403058a3d..0000000000 --- a/libraries/voxels/src/voxels_Log.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// voxels_Log.h -// hifi -// -// Created by Tobias Schwinger on 4/17/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __hifi__voxels_Log__ -#define __hifi__voxels_Log__ - -namespace voxels_lib { - - // variable that can be set from outside to redirect the log output - // of this library - extern int (* printLog)(char const*, ...); -} - -#endif /* defined(__hifi__voxels_Log__) */ -