1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
27 // File: vogl_console.cpp
28 #include "vogl_core.h"
29 #include "vogl_console.h"
30 #include "vogl_data_stream.h"
31 #include "vogl_threading.h"
32 #include "vogl_command_line_params.h"
33 #include "vogl_strutils.h"
40 #if VOGL_USE_LINUX_API
43 #include <sys/select.h>
45 #include <sys/ioctl.h>
50 static const char *s_msgnames[cCMTTotal] =
62 eConsoleMessageType console::m_default_category = cInfoConsoleMessage;
63 uint console::m_num_output_funcs;
64 console::console_func console::m_output_funcs[cMaxOutputFuncs];
65 bool console::m_prefixes = true;
66 bool console::m_output_disabled;
67 data_stream *console::m_pLog_stream;
68 mutex *console::m_pMutex;
69 uint console::m_num_messages[cCMTTotal];
70 bool console::m_at_beginning_of_line = true;
71 char console::m_tool_prefix[256];
73 const uint cConsoleBufSize = 256 * 1024;
79 m_pMutex = vogl_new(mutex);
83 void console::deinit()
87 vogl_delete(m_pMutex);
91 m_num_output_funcs = 0;
94 const char *console::get_message_type_str(eConsoleMessageType type)
96 if (type >= 0 && (type < VOGL_ARRAY_SIZE(s_msgnames)))
97 return s_msgnames[type];
101 eConsoleMessageType console::get_message_type_from_str(const char *str)
103 dynamic_string msgname = str;
105 for (uint type = 0; type < VOGL_ARRAY_SIZE(s_msgnames); type++)
107 if (msgname.compare(s_msgnames[type], false) == 0)
108 return (eConsoleMessageType)type;
110 return (eConsoleMessageType)-1;
113 void console::vprintf(eConsoleMessageType type, const char *p, va_list args)
120 m_num_messages[type]++;
122 static char buf[cConsoleBufSize];
125 uint buf_left = sizeof(buf);
127 if ((m_prefixes) && (m_at_beginning_of_line))
129 if (m_tool_prefix[0])
131 size_t l = strlen(m_tool_prefix);
132 memcpy(pDst, m_tool_prefix, l);
137 const char *pPrefix = NULL;
140 case cDebugConsoleMessage:
143 case cWarningConsoleMessage:
144 pPrefix = "Warning: ";
146 case cErrorConsoleMessage:
155 size_t l = strlen(pPrefix);
156 memcpy(pDst, pPrefix, l);
162 vogl::vogl_vsprintf_s(pDst, buf_left, p, args);
164 bool handled = false;
166 if (m_num_output_funcs)
168 for (uint i = 0; i < m_num_output_funcs; i++)
169 if (m_output_funcs[i].m_func(type, buf, m_output_funcs[i].m_pData))
173 if ((!m_output_disabled) && (!handled))
175 FILE *pFile = (type == cErrorConsoleMessage) ? stderr : stdout;
180 uint n = static_cast<uint>(strlen(buf));
181 m_at_beginning_of_line = (n) && (buf[n - 1] == '\n');
183 if ((type != cProgressConsoleMessage) && (m_pLog_stream))
186 dynamic_string tmp_buf(buf);
188 tmp_buf.translate_lf_to_crlf();
190 m_pLog_stream->printf("%s", tmp_buf.get_ptr());
191 m_pLog_stream->flush();
198 void console::printf(eConsoleMessageType type, const char *p, ...)
202 vprintf(type, p, args);
206 void console::printf(const char *p, ...)
210 vprintf(m_default_category, p, args);
214 void console::set_default_category(eConsoleMessageType category)
218 m_default_category = category;
221 eConsoleMessageType console::get_default_category()
225 return m_default_category;
228 void console::add_console_output_func(console_output_func pFunc, void *pData)
235 VOGL_ASSERT(m_num_output_funcs < cMaxOutputFuncs);
237 if (m_num_output_funcs < cMaxOutputFuncs)
239 m_output_funcs[m_num_output_funcs++] = console_func(pFunc, pData);
246 void console::remove_console_output_func(console_output_func pFunc)
253 for (int i = m_num_output_funcs - 1; i >= 0; i--)
255 if (m_output_funcs[i].m_func == pFunc)
257 m_output_funcs[i] = m_output_funcs[m_num_output_funcs - 1];
258 m_num_output_funcs--;
266 #define MESSAGE_VPRINTF_IMPL(_msgtype) \
269 vprintf(_msgtype, p, args); \
272 void console::progress(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cProgressConsoleMessage); }
273 void console::info(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cInfoConsoleMessage); }
274 void console::message(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cMessageConsoleMessage); }
275 void console::cons(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cConsoleConsoleMessage); }
276 void console::debug(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cDebugConsoleMessage); }
277 void console::warning(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cWarningConsoleMessage); }
278 void console::error(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cErrorConsoleMessage); }
279 void console::header1(const char *p, ...) { MESSAGE_VPRINTF_IMPL(cHeader1ConsoleMessage); }
281 #undef MESSAGE_VPRINTF_IMPL
283 #if VOGL_USE_WIN32_API
293 #elif VOGL_USE_LINUX_API
296 struct termios oldt, newt;
298 tcgetattr(STDIN_FILENO, &oldt);
300 newt.c_lflag &= ~(ICANON | ECHO);
301 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
303 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
307 // See http://www.flipcode.com/archives/_kbhit_for_Linux.shtml
310 static const int STDIN = 0;
311 static bool initialized = false;
315 // Use termios to turn off line buffering
317 tcgetattr(STDIN, &term);
318 term.c_lflag &= ~ICANON;
319 tcsetattr(STDIN, TCSANOW, &term);
325 ioctl(STDIN, FIONREAD, &bytesWaiting);
332 printf("Unimplemented!\n");
339 printf("Unimplemented!\n");